freenode/#lisp - IRC Chatlog
Search
22:07:47
gendl__
I'm used to Allegro CL where you can include or exclude things on a fairly fine-grained basis.
22:08:31
akoana
hi, I'm a bit confused by Peter Norvig's GPS example, he uses (defvar *state* ...) and (defvar *ops* ...) then (defun GPS (*state* goals *ops*) ...) as shown on https://github.com/norvig/paip-lisp/blob/master/docs/chapter4.md under 4.3 Stage 3: Implementation. Why does he use earmuffs in the defun lambda-list, is that anything special?
22:09:46
White_Flame
akoana: (defun GPS (*state* ...) ..) has the same effect as (let ((*state* ...)) ...) regarding the parameter
22:10:33
White_Flame
and (defun foo (params &optional (*var* *var*)) ...) is another pattern I've seen
22:14:06
akoana
thanks, hmm, not sure if I understand that, I'm quite new to Common Lisp... and I've not seen that anywhere else before (reading Practical Common Lisp too)...
22:16:54
saturn2
you can establish a dynamic binding on a special variable anywhere you can establish a lexical binding, including a function call
22:26:59
White_Flame
the earmuffs are of course just a naming convention. It's the defvar/defparameter that declares that the variable is "special", and thus (let ((*var* ...)) ...) is visible from anywhere in the same thread during the lifetime of that scope
22:27:33
White_Flame
(defun foo (&optional (*var* *var*)) ..) means that (foo) rebinds the variable to its existing value, and (foo 3) would rebind it to 3 within that scope
22:35:15
akoana
White_Flame: nevertheless, your excellent explanation was very insightful for me, thanks
22:39:27
akoana
(before I was wondering why *state* and *ops* weren't used at all in the body of gps, lol)
22:51:53
akoana
so (let ((*state* state-value) (*ops* ops-value) (gps goals))) would have the same effect as
22:56:50
akoana
sorry, got the parens wrong: (let ((*state* state-value) (*ops* ops-value)) (gps goals))
23:33:26
pjb
skami: So, you understand now that the problem is that the backquote reader macros reads an expression that may return some literal data, that must be considered immutable, but that you have modified with mapcan. The way to avoid it, is to remember that mapcan mutates the results of the mapped function.
23:34:21
pjb
skami: In those cases, you may use copy-list in the mapped function: (mapcan (lambda (x) (copy-list `(…))) …)
23:35:20
pjb
skami: or to use concatenate, if the mapped list is short (less than call-arguments-limit -2): (apply (function concatenate) 'list (mapcaR (lambda (x) `(…))))
23:36:22
pjb
skami: in general, beware with the mututating functions (non-consing functions, and other functions that modify the objects passed in parameter).
23:38:47
pjb
skami: now, there is not a lot of option to debug it (apart trying to locate where it's modified, by looking at the modified data), because while literal data is theorically immutable, in practice there's no difference between literal objects and normal objects, notably when you work at the REPL.
23:38:53
pjb
skami: The compiler could arrange things to put the literal data in a read-only segment, but since most implementation use lisp images, they dont save file formats with read-only data segments. Only ecl does that (compiling to elf files using gcc), but I don't know if it takes advantage of that to arrange for literal data to be read-only.
23:39:13
pjb
skami: some scheme implementations have immutable pairs, but this is quite inconvenient…
23:40:14
pjb
skami: that said, nothing would prevent you to patch your implementation to add such a feature. We could have a (ext:set-read-only object) extension such that if a mutator is applied later on the object, an error condition is signaled.
23:41:05
pjb
skami: then you could add calls to EXT:SET-READ-ONLY in reader macros, and in the QUOTE operator.
0:23:04
mister_m
What causes (subseq "a" 1) to result in ""? If I try to access the character at that same position, it would result in an out of bounds error.
0:27:29
aeth
It's probably permitted to allow iteration that ends with "", which is sort of like list processing (a lot of those algorithms end on NIL)
0:29:12
aeth
This whole way of thinking kind of parallels car/cdr, except that it's not efficient (since SUBSEQ is consing up a new string each time)
0:33:05
saturn2
it's permitted for the start of a sequence bounding index to equal the length of the sequence
0:35:29
aeth
it makes sense because it's sequence-generic including lists, e.g. (subseq (list #\a) 1) or (subseq (list #\a #\b #\c) 1) not just (subseq "a" 1) or (subseq "abc" 1)
0:37:25
saturn2
i would say it avoids a class of special cases you'd otherwise need to check for, and just makes logical sense
0:40:01
saturn2
the length of a subsequence is always (- end start), whether or not start and end are equal
0:40:17
mister_m
thanks for the clarification; I've been doing a lot of car/cdr iteration lately and that sort of jumped out as a "huh" moment
1:40:32
skami
pjb: Thanks for the clarification ! That would indeed be a fun projet to add such a read-only feature
1:50:31
stylewarning
APPEND, like most lisp functions, prefers to get the job done with the fewest copies
1:51:29
no-defun-allowed
APPEND could get confused if it tried to copy something that isn't a list, e.g. in (append '(1 2 3) 'a)
2:22:07
stylewarning
no-defun-allowed https://usercontent.irccloud-cdn.com/file/oVbhetyu/1620094917.JPG