unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Error: Setting the shell in sh-mode via a local variable does not work
@ 2015-12-28 16:35 Johannes Kastl
  2015-12-29  1:32 ` Emanuel Berg
  0 siblings, 1 reply; 38+ messages in thread
From: Johannes Kastl @ 2015-12-28 16:35 UTC (permalink / raw)
  To: help-gnu-emacs

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Dear all,

first of all, sorry if I failed in finding the answer to my question
on the web.

I have a file called 'whatever.spec.in', that basically is a rpm
spec file. (Technically, the spec file is generated from this file).
So, I'd like to have the nice rpm sh-mode, that my emacs uses for
files called 'whatever.spec'.

I googled a lot about major-modes, interpreter-mode-alist and all
kinds of stuff, even derived my own major-mode, but all fail, except
this:

(add-hook 'sh-mode-hook
          (lambda ()
            (if (string-match "\\.spec\\.in$" buffer-file-name)
                                (sh-set-shell "rpm"))))

This works. But:

The file contains some local variables at the end, that should
achieve the same:

# Local variables:
# mode: shell-script
# sh-shell: rpm
# end:

But regardless of what I put in the 'mode' and 'sh-shell' lines, I
always end up with shell-script[bash] when opening the file as
whatever.spec.in. If I rename it to whatever.spec, I get
shell-script[rpm].

Is this intended behaviour? Shouldn't the 'sh-shell:' line work? I
get no warning about malformed lines, so I think it is syntactically
correct.

Putting these local variables into an empty file call whatever.txt
gets me shell-script[bash], so apparently the 'mode:' line is used.

Thanks in advance, and please excuse the long descriptions...

Johannes

P.S.: System is OSX 10.10, emacs is GNU Emacs 24.5.1 from macports
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
Comment: Using GnuPG with SeaMonkey - http://www.enigmail.net/

iEYEARECAAYFAlaBZNIACgkQzi3gQ/xETbJLQgCfeBj+bVh4IzYCIb+CEMokqnko
MJYAn1dUEBM7w3VWCQa+/01gtKLcGulB
=r6ms
-----END PGP SIGNATURE-----



^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Error: Setting the shell in sh-mode via a local variable does not work
  2015-12-28 16:35 Error: Setting the shell in sh-mode via a local variable does not work Johannes Kastl
@ 2015-12-29  1:32 ` Emanuel Berg
  2015-12-29 18:33   ` Johannes Kastl
  2015-12-30 15:19   ` Teemu Likonen
  0 siblings, 2 replies; 38+ messages in thread
From: Emanuel Berg @ 2015-12-29  1:32 UTC (permalink / raw)
  To: help-gnu-emacs

Johannes Kastl <mail@ojkastl.de> writes:

> I have a file called 'whatever.spec.in', that
> basically is a rpm spec file. (Technically, the spec
> file is generated from this file). So, I'd like to
> have the nice rpm sh-mode, that my emacs uses for
> files called 'whatever.spec'.

I know two ways of doing that.

The first way is the best. I include my code as well.
It solves your problem at line 2:

(let ((modes '(
     ("\\.spec.in\\'"                                           . (lambda () (interactive) (progn (sh-mode) (sh-set-shell "rpm"))))
     ("\\.bal\\'"                                               . balance-mode)
     ("\\.gpi\\'"                                               . gnuplot-mode)
     ("\\.\\(glsl\\|oil\\|ssc\\|dfy\\)\\'"                      . c-mode)
     ("\\.lu\\'"                                                . lua-mode)
     ("\\.\\(service\\|list\\|theme\\|mailrc\\|sed\\|inc\\)\\'" . conf-mode)
     ("\\.pic\\'"                                               . nroff-mode)
     ("\\.xr\\'"                                                . conf-xdefaults-mode)
     ("inputrc\\'"                                              . conf-colon-mode)
     ("KILL\\'"                                                 . emacs-lisp-mode)
     ("README\\'"                                               . text-mode)
     ("\\.service\\'"                                           . emacs)
     )))
  (setq auto-mode-alist (append modes auto-mode-alist)) )

Then the second way. Here you have to add

    # spec.in

to every file. That isn't a lot of work, but I think
it is unaestethic. Files shouldn't be ABOUT
technology, they should be about what you can do, and
are doing WITH technology. Anyway:

    (setq magic-mode-alist '(("# spec.in" . (lambda () (interactive) (progn (sh-mode) (sh-set-shell "rpm"))))))

;; another example:
;; (setq magic-mode-alist '(("/\\* cpp \\*/" . c++-mode)))

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Error: Setting the shell in sh-mode via a local variable does not work
  2015-12-29  1:32 ` Emanuel Berg
@ 2015-12-29 18:33   ` Johannes Kastl
  2015-12-30 14:53     ` Emanuel Berg
  2015-12-30 15:19   ` Teemu Likonen
  1 sibling, 1 reply; 38+ messages in thread
From: Johannes Kastl @ 2015-12-29 18:33 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 696 bytes --]

Dear Emanuel,

thanks for your answer.

Am 29.12.15 schrieb Emanuel Berg:
> Johannes Kastl <mail@ojkastl.de> writes:
> 
>> I have a file called 'whatever.spec.in', that
>> basically is a rpm spec file. (Technically, the spec
>> file is generated from this file). So, I'd like to
>> have the nice rpm sh-mode, that my emacs uses for
>> files called 'whatever.spec'.
> 
> I know two ways of doing that.

Sorry if my question was rather long, but you are answering the part
that I already had a solution for. Adding an entry to .emacs to add a
hook so sh-mode works.

But my main question was, why the local variable "sh-shell: rpm" set
in a file does not work...

Johannes


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 244 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Error: Setting the shell in sh-mode via a local variable does not work
  2015-12-29 18:33   ` Johannes Kastl
@ 2015-12-30 14:53     ` Emanuel Berg
  2015-12-30 15:15       ` Robert Thorpe
  0 siblings, 1 reply; 38+ messages in thread
From: Emanuel Berg @ 2015-12-30 14:53 UTC (permalink / raw)
  To: help-gnu-emacs

Johannes Kastl <mail@johannes-kastl.de> writes:

> But my main question was, why the local variable
> "sh-shell: rpm" set in a file does not work...

What variable is that?

How is it set in a file?

In what way does it not work?

Or better yet: What do you want to do/happen, which
you cannot do/doesn't happen?

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Error: Setting the shell in sh-mode via a local variable does not work
  2015-12-30 14:53     ` Emanuel Berg
@ 2015-12-30 15:15       ` Robert Thorpe
  2015-12-30 15:30         ` Emanuel Berg
  2015-12-30 17:42         ` Johannes Kastl
  0 siblings, 2 replies; 38+ messages in thread
From: Robert Thorpe @ 2015-12-30 15:15 UTC (permalink / raw)
  To: Emanuel Berg, Johannes Kastl; +Cc: help-gnu-emacs

Emanuel Berg <embe8573@student.uu.se> writes:

> Johannes Kastl <mail@johannes-kastl.de> writes:
>
>> But my main question was, why the local variable
>> "sh-shell: rpm" set in a file does not work...
>
> What variable is that?
>
> How is it set in a file?
>
> In what way does it not work?
>
> Or better yet: What do you want to do/happen, which
> you cannot do/doesn't happen?

All of that was described in the original message that Johannes sent.

This bug report describes the same problem, but it says that it was
fixed in Emacs 24.5.
http://debbugs.gnu.org/cgi/bugreport.cgi?bug=17333

BR,
Robert Thorpe



^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Error: Setting the shell in sh-mode via a local variable does not work
  2015-12-29  1:32 ` Emanuel Berg
  2015-12-29 18:33   ` Johannes Kastl
@ 2015-12-30 15:19   ` Teemu Likonen
  2015-12-30 15:41     ` `append' vs. `nconc' (was: Re: Error: Setting the shell in sh-mode via a local variable does not work) Emanuel Berg
       [not found]     ` <mailman.1353.1451490125.843.help-gnu-emacs@gnu.org>
  1 sibling, 2 replies; 38+ messages in thread
From: Teemu Likonen @ 2015-12-30 15:19 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 1528 bytes --]

I'll add some simple Lisp programming notes that are unrelated to your
discussion. I hope you don't mind. :-)


Emanuel Berg [2015-12-29 02:32:38+01] wrote:

> (let ((modes '(

>      )))
>   (setq auto-mode-alist (append modes auto-mode-alist)) )

There you create a list MODES and then APPEND copies the whole list and
joins it to AUTO-MODE-ALIST. The original list is discarded. No problem,
it's just a configuration code. But in some other situation it might be
good idea to construct the list only once and use NCONC which only
traverses the lists through and modifies last conses to join it to the
next list:

    (let ((modes (list '(a . b)
                       ;; ...
                       )))
      (setq auto-mode-alist (nconc modes auto-mode-alist)))

Or:

    (setq auto-mode-alist
          (nconc (list '(a . b)
                       ;; ...
                       )
                 auto-mode-alist))

I used LIST function because, at least in Common Lisp, literal objects
(like lists created with QUOTE ' or literal strings) shouldn't be
modified. Consequences are undefined.

>     (setq magic-mode-alist '(("# spec.in" . (lambda () (interactive) (progn (sh-mode) (sh-set-shell "rpm"))))))

The PROGN is redundant because LAMBDA has an implicit PROGN:

    (lambda ()
      (interactive)
      (sh-mode)
      (sh-set-shell "rpm"))

-- 
/// Teemu Likonen   - .-..   <https://github.com/tlikonen> //
// PGP: 4E10 55DC 84E9 DFF6 13D7 8557 719D 69D3 2453 9450 ///

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Error: Setting the shell in sh-mode via a local variable does not work
  2015-12-30 15:15       ` Robert Thorpe
@ 2015-12-30 15:30         ` Emanuel Berg
  2015-12-30 17:42         ` Johannes Kastl
  1 sibling, 0 replies; 38+ messages in thread
From: Emanuel Berg @ 2015-12-30 15:30 UTC (permalink / raw)
  To: help-gnu-emacs

Robert Thorpe <rt@robertthorpeconsulting.com> writes:

>>> But my main question was, why the local variable
>>> "sh-shell: rpm" set in a file does not work...
>>
>> What variable is that?
>> How is it set in a file?
>> In what way does it not work?
>> Or better yet: What do you want to do/happen, which
>> you cannot do/doesn't happen?
>
> All of that was described in the original message
> that Johannes sent.

Okay...?

Getting the buffer in the desired mode works for me
with the code I provided, on:

    GNU Emacs 24.5.1 (x86_64-pc-linux-gnu, GTK+
    Version 3.18.6) of 2015-12-14 on binet, modified
    by Debian

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* `append' vs. `nconc' (was: Re: Error: Setting the shell in sh-mode via a local variable does not work)
  2015-12-30 15:19   ` Teemu Likonen
@ 2015-12-30 15:41     ` Emanuel Berg
  2015-12-30 16:37       ` `append' vs. `nconc' Teemu Likonen
       [not found]     ` <mailman.1353.1451490125.843.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 38+ messages in thread
From: Emanuel Berg @ 2015-12-30 15:41 UTC (permalink / raw)
  To: help-gnu-emacs

Teemu Likonen <tlikonen@iki.fi> writes:

> There you create a list MODES and then APPEND copies
> the whole list and joins it to AUTO-MODE-ALIST.
> The original list is discarded. No problem, it's
> just a configuration code. But in some other
> situation it might be good idea to construct the
> list only once and use NCONC which only traverses
> the lists through and modifies last conses to join
> it to the next list:
>
>     (let ((modes (list '(a . b) ;; ... ))) (setq
> auto-mode-alist (nconc modes auto-mode-alist)))

So what you are saying, if `append' is replaced by
`nconc', the same thing happens, only one less list
has to be created?

I have several appends in my source, is there
a rule-of-thumb when to use `append' and when to use
`nconc'?

> The PROGN is redundant because LAMBDA has an implicit
> PROGN

OK, cool.

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
       [not found]     ` <mailman.1353.1451490125.843.help-gnu-emacs@gnu.org>
@ 2015-12-30 16:18       ` Pascal J. Bourguignon
  0 siblings, 0 replies; 38+ messages in thread
From: Pascal J. Bourguignon @ 2015-12-30 16:18 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <embe8573@student.uu.se> writes:

> Teemu Likonen <tlikonen@iki.fi> writes:
>
>> There you create a list MODES and then APPEND copies
>> the whole list and joins it to AUTO-MODE-ALIST.
>> The original list is discarded. No problem, it's
>> just a configuration code. But in some other
>> situation it might be good idea to construct the
>> list only once and use NCONC which only traverses
>> the lists through and modifies last conses to join
>> it to the next list:
>>
>>     (let ((modes (list '(a . b) ;; ... ))) (setq
>> auto-mode-alist (nconc modes auto-mode-alist)))
>
> So what you are saying, if `append' is replaced by
> `nconc', the same thing happens, only one less list
> has to be created?
>
> I have several appends in my source, is there
> a rule-of-thumb when to use `append' and when to use
> `nconc'?

In doubt, use append.

If you are appending freshly consed lists, then it's safe to use nconc.

For example:

    (defun f (lists)
      (loop
        for list in lists
        append list))

    (defun f* (lists)
      (apply (function append) lists))

    (defun g (lists)
      (loop
         for list in lists
         nconc (mapcar (function 1+) list)))


In f, we are appending lists that are given to the function in the
parameter. Since we don't know whether those lists will be shared or
literal (we didn't specify anything about the lists), we should avoid
mutating them, therefore we use append in f.  A new copy of each of the
list will be used to build the result.

Notice that in f*, append does not copy the last list. We obtain a
result that shares structure with the arguments.  This may be a problem
or not, but in any case, that means that the result of f* is not a fresh
list, even if most of it is made of new cons cells, because of this
shared tail!

When you have a fixed set of lists to append, you can either use
concatenate, or add a '() as last argument to append:

        (concatenate 'list l1 l2 l3) --> a fresh list
        (append l1 l2 l3 '())        --> a fresh list
        (append l1 l2 l3)            --> a list sharing structure with l3.


In the case of g, since we create new lists (by way of mapcar), there
are no other reference to those lists, so we can use nconc, mutating
their last cdr to concatenate them without having to copy them.



Another way to say it: if you could use sort on your lists without
copy-list, then you can use nconc, otherwise you should use append:

(let ((l (list 1 2 3))
       s)
  (list (setf s (sort l '<))     ; ok
        (nconc s (list 4 5 6)))) ; ==> nconc ok

(let ((l '(1 2 3))
      s)
  (list (setf s (sort (copy-list l) '<))  ; copy-list needed
        (append l (list 4 5 6))           ; ==> use append
        (nconc s (list 4 5 6)))) ; s is a fresh copy ==> nconc ok


-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2015-12-30 15:41     ` `append' vs. `nconc' (was: Re: Error: Setting the shell in sh-mode via a local variable does not work) Emanuel Berg
@ 2015-12-30 16:37       ` Teemu Likonen
  2015-12-31  3:37         ` Emanuel Berg
                           ` (3 more replies)
  0 siblings, 4 replies; 38+ messages in thread
From: Teemu Likonen @ 2015-12-30 16:37 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 1046 bytes --]

Emanuel Berg [2015-12-30 16:41:51+01] wrote:

> So what you are saying, if `append' is replaced by `nconc', the same
> thing happens, only one less list has to be created?

Given the following:

    (append list1 list2 list3 last)

    (nconc list1 list2 list3 last)

APPEND copies LIST1, LIST2 and LIST3 but not LAST. All original lists
remain untouched but LAST becomes part of the new list returned by
APPEND.

NCONC doesn't copy lists but modifies LIST1's, LIST2's and LIST3's last
cons's CDR to point to the next list. NCONC returnes the joined list.
Only LAST remains untouched.

> I have several appends in my source, is there a rule-of-thumb when to
> use `append' and when to use `nconc'?

You can use NCONC if it's safe to modify the lists, that is, you know
where the lists come from and know how they are used. Don't modify a
list created with '(...). Use (list ...) instead.

-- 
/// Teemu Likonen   - .-..   <https://github.com/tlikonen> //
// PGP: 4E10 55DC 84E9 DFF6 13D7 8557 719D 69D3 2453 9450 ///

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Error: Setting the shell in sh-mode via a local variable does not work
  2015-12-30 15:15       ` Robert Thorpe
  2015-12-30 15:30         ` Emanuel Berg
@ 2015-12-30 17:42         ` Johannes Kastl
  1 sibling, 0 replies; 38+ messages in thread
From: Johannes Kastl @ 2015-12-30 17:42 UTC (permalink / raw)
  Cc: help-gnu-emacs

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Dear Robert,

Am 30.12.15 schrieb Robert Thorpe:
> 
> All of that was described in the original message that Johannes 
> sent.
> 
> This bug report describes the same problem, but it says that it
> was fixed in Emacs 24.5. 
> http://debbugs.gnu.org/cgi/bugreport.cgi?bug=17333

Thanks for the link. But I only read that it is fixed in version 25.1,
so I am not getting the fix in my 24.5.1.

> bug Marked as fixed in versions 25.1. Request was from Glenn 
> Morris <rgm <at> gnu.org> to control <at> debbugs.gnu.org. (Sat,
> 04 Oct 2014 16:36:04 GMT) Full text and rfc822 format available.

> bug No longer marked as fixed in versions 24.5. Request was from 
> Glenn Morris <rgm <at> gnu.org> to control <at> debbugs.gnu.org. 
> (Sat, 04 Oct 2014 16:36:04 GMT) Full text and rfc822 format 
> available.

OK, until I get 25.x on my mac I can live with my .emacs workaround.

Johannes
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
Comment: Using GnuPG with SeaMonkey - http://www.enigmail.net/

iEYEARECAAYFAlaEF4gACgkQzi3gQ/xETbJzowCeMd63viBiaQOdru4j6P6lHQI2
tOoAoJHvB94yHX124AhZuKwBaRviSedL
=repM
-----END PGP SIGNATURE-----



^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2015-12-30 16:37       ` `append' vs. `nconc' Teemu Likonen
@ 2015-12-31  3:37         ` Emanuel Berg
       [not found]         ` <mailman.1400.1451533083.843.help-gnu-emacs@gnu.org>
                           ` (2 subsequent siblings)
  3 siblings, 0 replies; 38+ messages in thread
From: Emanuel Berg @ 2015-12-31  3:37 UTC (permalink / raw)
  To: help-gnu-emacs

Teemu Likonen <tlikonen@iki.fi> writes:

> Given the following:
>
>     (append list1 list2 list3 last)
>
>     (nconc list1 list2 list3 last)
>
> APPEND copies LIST1, LIST2 and LIST3 but not LAST.
> All original lists remain untouched but LAST becomes
> part of the new list returned by APPEND.

 I think I always used `append' as if it were

    (append list1 ... listn '())

probably the reason it never bit me was I never did
much with the lists returned.

> NCONC doesn't copy lists but modifies LIST1's,
> LIST2's and LIST3's last cons's CDR to point to the
> next list. NCONC returnes the joined list. Only LAST
> remains untouched.

OK, so for example this:

(setq completion-ignored-extensions
      (append completion-ignored-extensions '(".bcf" ".run.xml")) )

Is better as:

    (nconc completion-ignored-extensions (list ".bcf" ".run.xml"))

?

>> I have several appends in my source, is there
>> a rule-of-thumb when to use `append' and when to
>> use `nconc'?
>
> You can use NCONC if it's safe to modify the lists,
> that is, you know where the lists come from and know
> how they are used. Don't modify a list created with
> '(...). Use (list ...) instead.

OK.

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
       [not found]         ` <mailman.1400.1451533083.843.help-gnu-emacs@gnu.org>
@ 2015-12-31  3:45           ` Pascal J. Bourguignon
  2015-12-31  4:00             ` Emanuel Berg
       [not found]             ` <mailman.1402.1451534421.843.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 38+ messages in thread
From: Pascal J. Bourguignon @ 2015-12-31  3:45 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <embe8573@student.uu.se> writes:

> OK, so for example this:
>
> (setq completion-ignored-extensions
>       (append completion-ignored-extensions '(".bcf" ".run.xml")) )
>
> Is better as:
>
>     (nconc completion-ignored-extensions (list ".bcf" ".run.xml"))
>
> ?

No.  You should never use nconc only for effect (just like delete, etc).

Always re-assign the modified list:

    (setf completion-ignored-extensions
          (nconc completion-ignored-extensions (list ".bcf" ".run.xml")))

otherwise it will break when the place is bound to nil.  (nil is a symbol
and cannot be mutated into a cons cell!).

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2015-12-30 16:37       ` `append' vs. `nconc' Teemu Likonen
  2015-12-31  3:37         ` Emanuel Berg
       [not found]         ` <mailman.1400.1451533083.843.help-gnu-emacs@gnu.org>
@ 2015-12-31  3:50         ` Emanuel Berg
       [not found]         ` <mailman.1401.1451533833.843.help-gnu-emacs@gnu.org>
  3 siblings, 0 replies; 38+ messages in thread
From: Emanuel Berg @ 2015-12-31  3:50 UTC (permalink / raw)
  To: help-gnu-emacs

Teemu Likonen <tlikonen@iki.fi> writes:

> Don't modify a list created with '(...). Use (list
> ...) instead.

What about the elements of the lists? If they are
themselves lists, can they be created with ' or is
this rule a "recursive descent" one?

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2015-12-31  3:45           ` Pascal J. Bourguignon
@ 2015-12-31  4:00             ` Emanuel Berg
  2015-12-31  9:22               ` tomas
       [not found]             ` <mailman.1402.1451534421.843.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 38+ messages in thread
From: Emanuel Berg @ 2015-12-31  4:00 UTC (permalink / raw)
  To: help-gnu-emacs

"Pascal J. Bourguignon" <pjb@informatimago.com>
writes:

>> OK, so for example this: (setq
>> completion-ignored-extensions (append
>> completion-ignored-extensions '(".bcf" ".run.xml"))
>> ) Is better as: (nconc completion-ignored-extensions
>> (list ".bcf" ".run.xml")) ?
>
> No. You should never use nconc only for effect (just
> like delete, etc).

What do you mean by "effect"?

The reason I thought it fitting was the definitions of
`append' and `ncons'. Here I want to change
`completion-ignored-extensions'. `append' doesn't
change it, which is why the assignment with `setq' was
there. If it can't be removed (well, in the form of
`setf'), there is still the gain of not creating the
list unnecessarily, which in this case is a matter of
principle but in other cases (with long lists) is
a performance bottleneck?

> Always re-assign the modified list:
>
>     (setf completion-ignored-extensions (nconc
> completion-ignored-extensions (list ".bcf"
> ".run.xml")))
>
> otherwise it will break when the place is bound to
> nil. (nil is a symbol and cannot be mutated into
> a cons cell!).

?

What place is bound to nil, when?

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
       [not found]             ` <mailman.1402.1451534421.843.help-gnu-emacs@gnu.org>
@ 2015-12-31  5:36               ` Pascal J. Bourguignon
  0 siblings, 0 replies; 38+ messages in thread
From: Pascal J. Bourguignon @ 2015-12-31  5:36 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <embe8573@student.uu.se> writes:

> "Pascal J. Bourguignon" <pjb@informatimago.com>
> writes:
>
>>> OK, so for example this: (setq
>>> completion-ignored-extensions (append
>>> completion-ignored-extensions '(".bcf" ".run.xml"))
>>> ) Is better as: (nconc completion-ignored-extensions
>>> (list ".bcf" ".run.xml")) ?
>>
>> No. You should never use nconc only for effect (just
>> like delete, etc).
>
> What do you mean by "effect"?

Side effect, same thing.

(nconc nil '(1 2 3)) has no side effect!

> The reason I thought it fitting was the definitions of
> `append' and `ncons'. Here I want to change
> `completion-ignored-extensions'. `append' doesn't
> change it, which is why the assignment with `setq' was
> there. If it can't be removed (well, in the form of
> `setf'), there is still the gain of not creating the
> list unnecessarily, which in this case is a matter of
> principle but in other cases (with long lists) is
> a performance bottleneck?
>
>> Always re-assign the modified list:
>>
>>     (setf completion-ignored-extensions (nconc
>> completion-ignored-extensions (list ".bcf"
>> ".run.xml")))
>>
>> otherwise it will break when the place is bound to
>> nil. (nil is a symbol and cannot be mutated into
>> a cons cell!).
>
> ?
>
> What place is bound to nil, when?

Any place you want, when it is.

    (let ((mylist '()))
       (nconc mylist (list 1 2 3))
       mylist)
    --> nil

    (setf completion-ignored-extensions '())
    (nconc completion-ignored-extensions  (list ".o"))
    completion-ignored-extensions
    --> nil


-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
       [not found]         ` <mailman.1401.1451533833.843.help-gnu-emacs@gnu.org>
@ 2015-12-31  5:37           ` Pascal J. Bourguignon
  2015-12-31  7:13             ` Emanuel Berg
       [not found]             ` <mailman.1406.1451546036.843.help-gnu-emacs@gnu.org>
  2015-12-31  7:31           ` Teemu Likonen
  1 sibling, 2 replies; 38+ messages in thread
From: Pascal J. Bourguignon @ 2015-12-31  5:37 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <embe8573@student.uu.se> writes:

> Teemu Likonen <tlikonen@iki.fi> writes:
>
>> Don't modify a list created with '(...). Use (list
>> ...) instead.
>
> What about the elements of the lists? If they are
> themselves lists, can they be created with ' or is
> this rule a "recursive descent" one?

You must remember the literal/immutable status of each item at each
level.

Since you are incapable of remembering it, you should assume that the
whole input data is immutable and write purely functional code (ie. use
append, not nconc) in general.


-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2015-12-31  5:37           ` Pascal J. Bourguignon
@ 2015-12-31  7:13             ` Emanuel Berg
  2015-12-31  9:30               ` tomas
       [not found]             ` <mailman.1406.1451546036.843.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 38+ messages in thread
From: Emanuel Berg @ 2015-12-31  7:13 UTC (permalink / raw)
  To: help-gnu-emacs

"Pascal J. Bourguignon" <pjb@informatimago.com>
writes:

> You must remember the literal/immutable status of
> each item at each level.
>
> Since you are incapable of remembering it, you
> should assume that the whole input data is immutable
> and write purely functional code (ie. use append,
> not nconc) in general.

OK, so you use `nconc' when you yourself create the
lists by hand and thus know they are not empty, all
the while using `list' and not ', and when done you
assign the result to a variable associated with a list
INSTEAD of using `nconc' directly because that
variable can hold the empty list, i.e. nil, which
`nconc' contrary to `append' cannot handle. And you do
this to save time!

Now I got it right!

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
       [not found]         ` <mailman.1401.1451533833.843.help-gnu-emacs@gnu.org>
  2015-12-31  5:37           ` Pascal J. Bourguignon
@ 2015-12-31  7:31           ` Teemu Likonen
  2015-12-31 18:35             ` Emanuel Berg
       [not found]             ` <mailman.1438.1451586967.843.help-gnu-emacs@gnu.org>
  1 sibling, 2 replies; 38+ messages in thread
From: Teemu Likonen @ 2015-12-31  7:31 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 578 bytes --]

Emanuel Berg [2015-12-31 04:50:19+01] wrote:

> Teemu Likonen <tlikonen@iki.fi> writes:
>> Don't modify a list created with '(...). Use (list ...) instead.
>
> What about the elements of the lists? If they are themselves lists,
> can they be created with ' or is this rule a "recursive descent" one?

NCONC doesn't touch the elements (i.e., CAR values of conses) so this is
fine:

    (setq foo (nconc (list '(a . 1) '(b . 2)) foo))

-- 
/// Teemu Likonen   - .-..   <https://github.com/tlikonen> //
// PGP: 4E10 55DC 84E9 DFF6 13D7 8557 719D 69D3 2453 9450 ///

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
       [not found]             ` <mailman.1406.1451546036.843.help-gnu-emacs@gnu.org>
@ 2015-12-31  8:54               ` Pascal J. Bourguignon
  0 siblings, 0 replies; 38+ messages in thread
From: Pascal J. Bourguignon @ 2015-12-31  8:54 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <embe8573@student.uu.se> writes:

> "Pascal J. Bourguignon" <pjb@informatimago.com>
> writes:
>
>> You must remember the literal/immutable status of
>> each item at each level.
>>
>> Since you are incapable of remembering it, you
>> should assume that the whole input data is immutable
>> and write purely functional code (ie. use append,
>> not nconc) in general.
>
> OK, so you use `nconc' when you yourself create the
> lists by hand and thus know they are not empty, all
> the while using `list' and not ', and when done you
> assign the result to a variable associated with a list
> INSTEAD of using `nconc' directly because that
> variable can hold the empty list, i.e. nil, which
> `nconc' contrary to `append' cannot handle. And you do
> this to save time!

nconc can handle nil.  But in that case, it doesn't modify it! It just
return the nconc'ed list:

(nconc nil nil (list 1 2 3) nil (list 3 4 5) nil)
--> (1 2 3 3 4 5)

(let ((list nil))
   (list (nconc list nil (list 1 2 3) nil (list 3 4 5) nil)
         list))
--> ((1 2 3 3 4 5) ; returned
     nil) ; list is still bound to nil which cannot be mutated.

(let ((list nil))
   (list (setf list (nconc list nil (list 1 2 3) nil (list 3 4 5) nil))
         list))
--> ((1 2 3 3 4 5)  ; returned and set to list
     (1 2 3 3 4 5)) ; list has been set with setf, so it's ok.

The only case where you could forget the setf, is when you just return
the nconc'ed result:

    (defun f (list to-add)
      (setf list (nconc list to-add))
      list)

can be written just:

    (defun f (list to-add)
      (nconc list to-add))

But in such a case, notice that you will have to bind or use the result
of f:

   (let ((list (list 1 2 3)))
     (setf list (f list (list 4 5 6)))
     list)
   --> (1 2 3 4 5 6)

It's like with delete, but for the opposite reason: delete cannot
transform a cons cell into the symbol nil:

    (delete 1 (list 1)) --> nil

But in anycase, it is not specified how delete (or delq) modifies the
list structure, so even:

     (let ((list (list 1 2 3 4 5)))
        (delete 3 list)
        list)

is not guaranteed to return: (1 2 4 5)

Instead, you have to write:

     (let ((list (list 1 2 3 4 5)))
        (setf list (delete 3 list))
        list)
     --> (1 2 4 5)

to ensure that list is bound to the wanted result of delete.

It is general: when you have a function that mutate a structure and
return the new structure, if the exact way how it mutates it is not
specified or if it cannot always mutate it (eg for lists, when there's
an impossible transition nil <-> cons cell), you have use the result of
the function and cannot count on the mutation.

So, to use a non-mutating function:

    (setf list (remove element list))
    (setf list (append list tail))

and to use a mutating function:

    (setf list (delete element list))
    (setf list (nconc list tail))

In both cases you must rebind the result.


> Now I got it right!

almost. ;-)

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2015-12-31  4:00             ` Emanuel Berg
@ 2015-12-31  9:22               ` tomas
  2015-12-31 18:48                 ` Emanuel Berg
  0 siblings, 1 reply; 38+ messages in thread
From: tomas @ 2015-12-31  9:22 UTC (permalink / raw)
  To: help-gnu-emacs

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Thu, Dec 31, 2015 at 05:00:07AM +0100, Emanuel Berg wrote:
> "Pascal J. Bourguignon" <pjb@informatimago.com>
> writes:
> 
> >> OK, so for example this: (setq
> >> completion-ignored-extensions (append
> >> completion-ignored-extensions '(".bcf" ".run.xml"))
> >> ) Is better as: (nconc completion-ignored-extensions
> >> (list ".bcf" ".run.xml")) ?
> >
> > No. You should never use nconc only for effect (just
> > like delete, etc).
> 
> What do you mean by "effect"?

Side effect, the big lurking Monster for functional programmers:

  (defvar foo 15)

  (defun monster ()
    (setq foo 42))

  (monster)
  ;; now foo is 42: Gaaah!
  (message "%S" foo)

Nconc has a side effect: after calling it, many of the lists are
changed.

Side effects make things more "interesting", because now things depend
on the order of evaluation of things: it does matter, e.g. wheter you
evaluate the arguments of a function (call) left-to-right or right-to-left
(or random!). Things like that. The equivalent in C might be

  int i = 42;
  printf("%d %d %d\n", i++, i++, i++)

or the classic:

  a[i] = i++;

(which leads to undefined behaviour, because compiler writers need some
wiggling room to make efficient compilers!).

Sometimes you call functions because you *want* the side effect (aka
"calling for effect"), as in

  (message "Happy New Year!")

So-called "pure functional languages" have to go towards some "interesting"
contortions for that.

Regards
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlaE8+0ACgkQBcgs9XrR2kYE0QCfcFXQTDijDWoh4GQKerTVEuuw
ragAn2SMKqwM3yfp5LQQt5MLQAEgdMjV
=iPp+
-----END PGP SIGNATURE-----



^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2015-12-31  7:13             ` Emanuel Berg
@ 2015-12-31  9:30               ` tomas
  2015-12-31 17:56                 ` side effects, list sharing [was: `append' vs. `nconc'] Drew Adams
                                   ` (2 more replies)
  0 siblings, 3 replies; 38+ messages in thread
From: tomas @ 2015-12-31  9:30 UTC (permalink / raw)
  To: help-gnu-emacs

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Thu, Dec 31, 2015 at 08:13:41AM +0100, Emanuel Berg wrote:
> "Pascal J. Bourguignon" <pjb@informatimago.com>
> writes:
> 
> > You must remember the literal/immutable status of
> > each item at each level.
> >
> > Since you are incapable of remembering it, you
> > should assume that the whole input data is immutable
> > and write purely functional code (ie. use append,
> > not nconc) in general.
> 
> OK, so you use `nconc' when you yourself create the
> lists by hand and thus know they are not empty, all
> the while using `list' and not ', and when done you
> assign the result to a variable associated with a list
> INSTEAD of using `nconc' directly because that
> variable can hold the empty list, i.e. nil, which
> `nconc' contrary to `append' cannot handle. And you do
> this to save time!

Or, to squint differently at it: you use nconc when "nobody
is looking", i.e. when you *know* that there are no references
to the data being mutated (unless you *want* that the world
changes for those other watchers too).

OTOH, nconc is "just an optimization", because GC isn't ideal.
So a good rule of thumb:

 - it's very obvious
   It's a local value you are keeping in your little scope.
   (One might argue that then, it's an idiomatic way to
   emphasize this fact to the (human) reader...)

 - you are really pressed for time 
   It's somewhere deep in many nested loops.

Otherwise... just don't use it.

Regards
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlaE9cUACgkQBcgs9XrR2kZmSQCfRKgjktl8mIPS6/Eh/XkkHNiE
0E8AoIFZKrKi9bB1q0Ujul/IdXad8WX6
=Q8vS
-----END PGP SIGNATURE-----



^ permalink raw reply	[flat|nested] 38+ messages in thread

* side effects, list sharing   [was: `append' vs. `nconc']
  2015-12-31  9:30               ` tomas
@ 2015-12-31 17:56                 ` Drew Adams
  2015-12-31 19:00                   ` Emanuel Berg
  2015-12-31 18:51                 ` `append' vs. `nconc' Emanuel Berg
       [not found]                 ` <mailman.1440.1451588113.843.help-gnu-emacs@gnu.org>
  2 siblings, 1 reply; 38+ messages in thread
From: Drew Adams @ 2015-12-31 17:56 UTC (permalink / raw)
  To: tomas, help-gnu-emacs

Thomas wrote:

> nconc is "just an optimization", because GC isn't ideal.
> So a good rule of thumb:
>   - it's very obvious ...
>   - you are really pressed for time ...
> Otherwise... just don't use it.

_Just don't use side effects_, at least those such as `nconc'
that share list structure, is the right starting place, and is
definitely the best rule of thumb.  You will _never_ go wrong
with it as your motto, in code you write.

If, however, you modify code written by others, who do not
play by this simple rule, then you had better learn what it
is all about.  (By "you" I mean each of us.)

Lisp is Lisp.  It is not Haskell or lambda calculus.

The two guidelines that Thomas listed are fine.  But the most
important use case for side effects using functions such as
`nconc' has to do primarily with neither space nor time
optimization: it is _sharing of list structure_ for combined
effect.

IOW, precisely the thing that can get you in trouble is the
main reason for intentionally using such functions: you
_want_ a change in one list to automatically change another
in the same way.  You do that by making them share some list
structure.

And yes, such things are fraught with gotchas, exactly like
the sharing of data using global variables.

When a bug rears its ugly head, it is just as likely that you
see only an ugly pimple on a foot or elbow or tail, and not
on the head at all, and it is likely that the noticeable
manifestation will occur only long after you made the change
to the list.  Bonjour les dégats !

Again, this is _exactly_ like the problems that arise from
using global variables.  They closely _couple_ together
different program pieces and their logic.  And this is used
in Lisp for exactly the same reason that shared data has
been used in other languages.

IOW, this is nothing new, even if its form might be new to 
someone who is unused to Lisp lists.  If you are coming to
Lisp from Haskell then you might have a lot to learn in
this regard.  If you are coming to it from Fortran then
the data-sharing part is not new (but the rest of Lisp is).

This is Real Lisp (TM), and it is not for the faint-hearted.
And yes, we can all be bitten occasionally by the gotchas,
and we _all are_.  And it can be difficult to track down the
culprit code.  Difficult or fun, depending on how much free
time you have and how much you enjoy playing with Lisp.

You can say that "nconc is 'just an optimization'", but that
is true only for some very general, or very complicated and
program-specific, meaning of "optimization".  And it is not
necessarily "because GC isn't ideal".

If you never step off into List-Modification Land then it
is not important how such so-called "destructive" functions
are characterized.

But if you do venture there, e.g., to modify some existing
code that shares list structure, then know how, where, and
why the structure is shared, to start with.  And even then,
keep your wits about you, and keep a look out for dragons
over your shoulder and under your feet.



^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2015-12-31  7:31           ` Teemu Likonen
@ 2015-12-31 18:35             ` Emanuel Berg
  2015-12-31 20:04               ` Teemu Likonen
       [not found]             ` <mailman.1438.1451586967.843.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 38+ messages in thread
From: Emanuel Berg @ 2015-12-31 18:35 UTC (permalink / raw)
  To: help-gnu-emacs

Teemu Likonen <tlikonen@iki.fi> writes:

> NCONC doesn't touch the elements (i.e., CAR values
> of conses) so this is fine:
>
>     (setq foo (nconc (list '(a . 1) '(b . 2)) foo))

OK!

Because, many cases where I replaced `apply' by
`nconc' were lists of lists.

What is the reason one has to use `list'? (I suppose
the ` isn't safe, either.)

And: In Pascal's examples he always used `setf'.
The help says it can be used for places as well as for
symbols. In the examples tho there has been only
symbols if I'm not mistaken.

(setq completion-ignored-extensions
      (nconc completion-ignored-extensions (list ".bcf" ".run.xml")) )

(setq ispell-skip-region-alist
      (nconc ispell-skip-region-alist (list '("`" . "\\(`\\|'\\)"))) )

(let*((write
       (list
         '("hp"       "http://user.it.uu.se/~embe8573")
         '("lenght"   "length")
         ;; ...
         '("thedate"  "" (lambda () (interactive) (show-time-and-date t))) ; INSERT
         ))
      (groups (list
                '("ctt" "comp.text.tex")
                '("geg" "gmane.emacs.gnus")
                ;; ...
                ))
      (both (nconc write groups)))
  (define-abbrev-table 'global-abbrev-table both) )

(let ((modes (list
     '("\\.bal\\'"  . balance-mode)
     '("\\.gpi\\'"  . gnuplot-mode)
     ;; ...
     )))
  (setq auto-mode-alist (nconc modes auto-mode-alist)) )

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2015-12-31  9:22               ` tomas
@ 2015-12-31 18:48                 ` Emanuel Berg
  0 siblings, 0 replies; 38+ messages in thread
From: Emanuel Berg @ 2015-12-31 18:48 UTC (permalink / raw)
  To: help-gnu-emacs

<tomas@tuxteam.de> writes:

> Side effect, the big lurking Monster for functional
> programmers:
>
>   (defvar foo 15)
>
>   (defun monster () (setq foo 42))
>
>   (monster) ;; now foo is 42: Gaaah! (message "%S"
> foo)
>
> Nconc has a side effect: after calling it, many of the
> lists are changed.

However, because of the potential situation with
a symbol being nil or the empty list, `nconc' can't
really be used only "for effect" - so it should return
the list and that in turn be assigned!

So a little bit of functional programming still has to
be employed! (Not that the FP people has the monopoly
on returning stuff tho they might think so themselves
in their opium dreams.)

On the other hand, `append' isn't side-effect free!

    (setq *digits* '(1 2 3 4 5))
    (setq *chars*  '(a b c d e))
    (setq *appended-list* (append *digits* *chars*))
    (setf (car (last *appended-list*)) 'x)
    (insert (format " ; %s" *appended-list*)) ; (1 2 3 4 5 a b c d x)
    (insert (format " ; %s" *chars*)) ; (a b c d x)

Perhaps (concatenate 'list ...) is the
functional function?

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2015-12-31  9:30               ` tomas
  2015-12-31 17:56                 ` side effects, list sharing [was: `append' vs. `nconc'] Drew Adams
@ 2015-12-31 18:51                 ` Emanuel Berg
       [not found]                 ` <mailman.1440.1451588113.843.help-gnu-emacs@gnu.org>
  2 siblings, 0 replies; 38+ messages in thread
From: Emanuel Berg @ 2015-12-31 18:51 UTC (permalink / raw)
  To: help-gnu-emacs

<tomas@tuxteam.de> writes:

> - it's very obvious It's a local value you are
> keeping in your little scope. (One might argue that
> then, it's an idiomatic way to emphasize this fact
> to the (human) reader...)

The thing here is, when it is very obvious and
everything is small and easy to handle, what is the
actual gain in time and space not using `append'?

Answer:

    -> 0

But OK, as a matter of principle it can be a cool
thing to know/do.

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: side effects, list sharing   [was: `append' vs. `nconc']
  2015-12-31 17:56                 ` side effects, list sharing [was: `append' vs. `nconc'] Drew Adams
@ 2015-12-31 19:00                   ` Emanuel Berg
  2015-12-31 19:15                     ` Drew Adams
  0 siblings, 1 reply; 38+ messages in thread
From: Emanuel Berg @ 2015-12-31 19:00 UTC (permalink / raw)
  To: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:

> _Just don't use side effects_, at least those such
> as `nconc' that share list structure, is the right
> starting place, and is definitely the best rule of
> thumb. You will _never_ go wrong with it as your
> motto, in code you write.

As a rule of thumb it is too general to be useful, as
a motto I suppose it is OK.

> Lisp is Lisp. It is not Haskell or lambda calculus.

That's exactly right. There was a guy here, namely
Rusi, who spent much effort advocating FP. We'll see
if he jumps into the discussion.

> The two guidelines that Thomas listed are fine.
> But the most important use case for side effects using
> functions such as `nconc' has to do primarily with
> neither space nor time optimization: it is _sharing of
> list structure_ for combined effect.

Yeah, we understand that is what `nconc' do. I think
the reason Thomas said that is that was the direction
the discussion went because it all started with having
my configuration not having to copy the list as would
happen with `append'.

But other then time/space optimization, what would you
say is the reason not to play it safe/sane and just
return stuff, new stuff if necessary, but instead
modify them directly?

Besides a possible time/space gain, I can only see
really creative/insane programmers doing that!

> This is Real Lisp (TM), and it is not for the
> faint-hearted. And yes, we can all be bitten
> occasionally by the gotchas, and we _all are_.
> And it can be difficult to track down the culprit
> code. Difficult or fun, depending on how much free
> time you have and how much you enjoy playing
> with Lisp.

Indeed, only I think it is the other way around:
I would get an heart attack instantly if I were to
think, argue, and code like the FP fanatics.

Math is another thing tho because math only has to
make sense and be correct, it doesn't have to work.
Programming has to work and if it makes sense all the
better :)

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: side effects, list sharing   [was: `append' vs. `nconc']
  2015-12-31 19:00                   ` Emanuel Berg
@ 2015-12-31 19:15                     ` Drew Adams
  2016-01-01 13:20                       ` Emanuel Berg
  0 siblings, 1 reply; 38+ messages in thread
From: Drew Adams @ 2015-12-31 19:15 UTC (permalink / raw)
  To: Emanuel Berg, help-gnu-emacs

> But other then time/space optimization, what would you
> say is the reason not to play it safe/sane and just
> return stuff, new stuff if necessary, but instead
> modify them directly?

You will know it if you see it or when you really need it!

If you don't see a need for sharing list structure then
playing it safe/sane is the right approach.

If you are modifying someone else's code, and you see
structure-modifying code, that is, code that indicates
that list-sharing is going on, then you need to wake up
and take that into consideration.

Otherwise, there is no need to worry about it - just
play it safe/sane and Bob's your uncle.

If you just want to learn about such use cases, look
through existing Lisp code for uses of `setcar' and
company.  I can almost guarantee that they are not
used gratuitously.

And unless you see them used in a clearly local and
safe/encapsulated fashion, look around for what's
really going on, to see why that code uses list-sharing.



^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2015-12-31 18:35             ` Emanuel Berg
@ 2015-12-31 20:04               ` Teemu Likonen
  2016-01-01 13:23                 ` Emanuel Berg
  0 siblings, 1 reply; 38+ messages in thread
From: Teemu Likonen @ 2015-12-31 20:04 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 1106 bytes --]

Emanuel Berg [2015-12-31 19:35:52+01] wrote:

> Teemu Likonen <tlikonen@iki.fi> writes:
>>     (setq foo (nconc (list '(a . 1) '(b . 2)) foo))

> What is the reason one has to use `list'? (I suppose the ` isn't safe,
> either.)

LIST function creates a fresh list when it is evaluated, usually at
runtime. The following applies to the Common Lisp language: Literal
objects created with ' ` (QUOTE ...) "string" etc. might be created at
compile time. Such objects might even be shared by all instances of such
literal object. Common Lisp compilers are allowed to do that. So, the
literal list '(a b c) in one place might actually become the very same
(as in EQ) object as literal '(a b c) in somewhere else. If you mutate
one object the results may show everywhere, which is not usually wanted.

Even though it may not apply to Emacs Lisp or all Common Lisp compilers
it's good habit to not mutate literally created objects. Be functional
with them! :-)

-- 
/// Teemu Likonen   - .-..   <https://github.com/tlikonen> //
// PGP: 4E10 55DC 84E9 DFF6 13D7 8557 719D 69D3 2453 9450 ///

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
       [not found]                 ` <mailman.1440.1451588113.843.help-gnu-emacs@gnu.org>
@ 2016-01-01  2:53                   ` Barry Margolin
  2016-01-01 13:26                     ` Emanuel Berg
  0 siblings, 1 reply; 38+ messages in thread
From: Barry Margolin @ 2016-01-01  2:53 UTC (permalink / raw)
  To: help-gnu-emacs

In article <mailman.1440.1451588113.843.help-gnu-emacs@gnu.org>,
 Emanuel Berg <embe8573@student.uu.se> wrote:

> <tomas@tuxteam.de> writes:
> 
> > - it's very obvious It's a local value you are
> > keeping in your little scope. (One might argue that
> > then, it's an idiomatic way to emphasize this fact
> > to the (human) reader...)
> 
> The thing here is, when it is very obvious and
> everything is small and easy to handle, what is the
> actual gain in time and space not using `append'?
> 
> Answer:
> 
>     -> 0
> 
> But OK, as a matter of principle it can be a cool
> thing to know/do.

NCONC was created at least 40 years ago, when computers were slow and 
had very little memory (a modern cellphone is has the power of a roomful 
of 70's-era mainframes). And garbage collection was also very slow 
(generational GC hadn't been developed yet).

So optimizations like NCONC could be very useful back then. These days, 
the benefit is probably very little.

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
       [not found]             ` <mailman.1438.1451586967.843.help-gnu-emacs@gnu.org>
@ 2016-01-01  6:25               ` Pascal J. Bourguignon
  2016-01-01 13:31                 ` Emanuel Berg
  0 siblings, 1 reply; 38+ messages in thread
From: Pascal J. Bourguignon @ 2016-01-01  6:25 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg <embe8573@student.uu.se> writes:

> What is the reason one has to use `list'? (I suppose
> the ` isn't safe, either.)

list returns a fresh list. ` doesn't. ` may return a structure that
shares literal substructures with others.

Typically, it will be a tail, but it can also be some cars:

    `((a . b) (c . ,x) ,@y d e f)

could translate to:

    (list* '(a . b) (cons 'c x) (append y '(d e f)))

or something similar.  Then each time you execute it, you get a list
whose tail is the same literal (d e f), and whose car is the same
literal cons (a . b).


> And: In Pascal's examples he always used `setf'.
> The help says it can be used for places as well as for
> symbols. In the examples tho there has been only
> symbols if I'm not mistaken.

It's simplier to forget about set and setq, and always use setf.
That frees two neurons to think about other things.


-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: side effects, list sharing   [was: `append' vs. `nconc']
  2015-12-31 19:15                     ` Drew Adams
@ 2016-01-01 13:20                       ` Emanuel Berg
  0 siblings, 0 replies; 38+ messages in thread
From: Emanuel Berg @ 2016-01-01 13:20 UTC (permalink / raw)
  To: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:

>> But other then time/space optimization, what would
>> you say is the reason not to play it safe/sane and
>> just return stuff, new stuff if necessary, but
>> instead modify them directly?
>
> You will know it if you see it or when you really
> need it!

Morpheus:

    Unfortunately, no one can be *told* what the
    Matrix is. You have to see it for yourself.

> If you don't see a need for sharing list structure
> then playing it safe/sane is the right approach.

Say that you do a rope-and-wheel mechanism to have
a bathroom door close automatically. As a weight, you
use a bottle. How do you tie the bottle to the rope?
Do you just tie it as a kid would, with random loops
all over, and then pull tight with your muscles? Or do
you look up a professional knot in the BIG BOOK
OF KNOTS?

Just as using advanced Lisp to solve perhaps trivial,
and definitely non-critical problems of Emacs
configuration, it can be seen as hitting the
heavy bag.

If the real deal, whatever that is, ever appears,
you'll be more ready than otherwise. If it doesn't
appear, you at least have a good looking knot, some
cool Elisp, and a fit body!

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2015-12-31 20:04               ` Teemu Likonen
@ 2016-01-01 13:23                 ` Emanuel Berg
  2016-01-01 14:02                   ` Teemu Likonen
  0 siblings, 1 reply; 38+ messages in thread
From: Emanuel Berg @ 2016-01-01 13:23 UTC (permalink / raw)
  To: help-gnu-emacs

Teemu Likonen <tlikonen@iki.fi> writes:

> LIST function creates a fresh list when it is
> evaluated, usually at runtime. The following applies
> to the Common Lisp language: Literal objects created
> with ' ` (QUOTE ...) "string" etc. might be created
> at compile time. Such objects might even be shared
> by all instances of such literal object. Common Lisp
> compilers are allowed to do that. So, the literal
> list '(a b c) in one place might actually become the
> very same (as in EQ) object as literal '(a b c) in
> somewhere else. If you mutate one object the results
> may show everywhere, which is not usually wanted.
>
> Even though it may not apply to Emacs Lisp or all
> Common Lisp compilers it's good habit to not mutate
> literally created objects. Be functional with them!

OK, then what functions, other than `nconc', are
mutators (or, how do you now)?

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2016-01-01  2:53                   ` Barry Margolin
@ 2016-01-01 13:26                     ` Emanuel Berg
  0 siblings, 0 replies; 38+ messages in thread
From: Emanuel Berg @ 2016-01-01 13:26 UTC (permalink / raw)
  To: help-gnu-emacs

Barry Margolin <barmar@alum.mit.edu> writes:

>> The thing here is, when it is very obvious and
>> everything is small and easy to handle, what is the
>> actual gain in time and space not using `append'?
>> 
>> Answer:
>> 
>>     -> 0
>> 
>> But OK, as a matter of principle it can be a cool
>> thing to know/do.
>
> NCONC was created at least 40 years ago, when
> computers were slow and had very little memory (a
> modern cellphone is has the power of a roomful of
> 70's-era mainframes). And garbage collection was
> also very slow (generational GC hadn't been
> developed yet).
>
> So optimizations like NCONC could be very useful
> back then. These days, the benefit is probably
> very little.

Q.E.D. :)

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2016-01-01  6:25               ` Pascal J. Bourguignon
@ 2016-01-01 13:31                 ` Emanuel Berg
  2016-01-01 15:04                   ` Drew Adams
  0 siblings, 1 reply; 38+ messages in thread
From: Emanuel Berg @ 2016-01-01 13:31 UTC (permalink / raw)
  To: help-gnu-emacs

"Pascal J. Bourguignon" <pjb@informatimago.com>
writes:

> list returns a fresh list. ` doesn't. ` may return
> a structure that shares literal substructures
> with others.

I have lots of ' and ` and instead of examining all
those cases I think it is easier to look for the
mutators, and see if ' or ` are used in
their vicinity.

I found this page:

    http://www.emacswiki.org/emacs/DestructiveOperations

> It's simplier to forget about set and setq, and
> always use setf.

Oh, no! I have 207 `setq' in my initialization!

> That frees two neurons to think about other things.

I think we have spent too much time together lately:
now we are starting to *think* the same way!

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2016-01-01 13:23                 ` Emanuel Berg
@ 2016-01-01 14:02                   ` Teemu Likonen
  2016-01-01 18:31                     ` Emanuel Berg
  0 siblings, 1 reply; 38+ messages in thread
From: Teemu Likonen @ 2016-01-01 14:02 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 350 bytes --]

Emanuel Berg [2016-01-01 14:23:26+01] wrote:

> OK, then what functions, other than `nconc', are mutators (or, how do
> you now)?

A manual or the specification says it. Such operation is called
"destructive".

-- 
/// Teemu Likonen   - .-..   <https://github.com/tlikonen> //
// PGP: 4E10 55DC 84E9 DFF6 13D7 8557 719D 69D3 2453 9450 ///

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: `append' vs. `nconc'
  2016-01-01 13:31                 ` Emanuel Berg
@ 2016-01-01 15:04                   ` Drew Adams
  0 siblings, 0 replies; 38+ messages in thread
From: Drew Adams @ 2016-01-01 15:04 UTC (permalink / raw)
  To: Emanuel Berg, help-gnu-emacs

> I have lots of ' and ` and instead of examining all
> those cases I think it is easier to look for the
> mutators, and see if ' or ` are used in their vicinity.
>
> I found this page: http://www.emacswiki.org/emacs/DestructiveOperations

Yes, just keep an eye out for the mutators; that's all.
And it's not about ' or `.  Whenever "destructive" functions
are involved, you need to keep an eye out more generally -
but specifically wherever the structures get mutated or used
(referenced).




^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: `append' vs. `nconc'
  2016-01-01 14:02                   ` Teemu Likonen
@ 2016-01-01 18:31                     ` Emanuel Berg
  0 siblings, 0 replies; 38+ messages in thread
From: Emanuel Berg @ 2016-01-01 18:31 UTC (permalink / raw)
  To: help-gnu-emacs

Teemu Likonen <tlikonen@iki.fi> writes:

>> OK, then what functions, other than `nconc', are
>> mutators (or, how do you now)?
>
> A manual or the specification says it.
> Such operation is called "destructive".

A function is destructive if it changes its arguments.
I suppose it is even more destructive if it changes
things that aren't even passed to the function.

What I can tell this definition is straightforward so
it is rather a question of knowing what functions are
like that.

For example, the help for `nconc' says:

    (nconc &rest LISTS)

    Concatenate any number of lists by altering them.
    Only the last argument is not altered, and need not be
    a list.

And `append':

    (append &rest SEQUENCES)

    Concatenate all the arguments and make the result
    a list.
    The result is a list whose elements are the
    elements of all the arguments.
    Each argument may be a list, vector or string.
    The last argument is not copied, just used as the
    tail of the new list.

You need to be attentive but if you are, sure, it
is there.

-- 
underground experts united
http://user.it.uu.se/~embe8573




^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2016-01-01 18:31 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-12-28 16:35 Error: Setting the shell in sh-mode via a local variable does not work Johannes Kastl
2015-12-29  1:32 ` Emanuel Berg
2015-12-29 18:33   ` Johannes Kastl
2015-12-30 14:53     ` Emanuel Berg
2015-12-30 15:15       ` Robert Thorpe
2015-12-30 15:30         ` Emanuel Berg
2015-12-30 17:42         ` Johannes Kastl
2015-12-30 15:19   ` Teemu Likonen
2015-12-30 15:41     ` `append' vs. `nconc' (was: Re: Error: Setting the shell in sh-mode via a local variable does not work) Emanuel Berg
2015-12-30 16:37       ` `append' vs. `nconc' Teemu Likonen
2015-12-31  3:37         ` Emanuel Berg
     [not found]         ` <mailman.1400.1451533083.843.help-gnu-emacs@gnu.org>
2015-12-31  3:45           ` Pascal J. Bourguignon
2015-12-31  4:00             ` Emanuel Berg
2015-12-31  9:22               ` tomas
2015-12-31 18:48                 ` Emanuel Berg
     [not found]             ` <mailman.1402.1451534421.843.help-gnu-emacs@gnu.org>
2015-12-31  5:36               ` Pascal J. Bourguignon
2015-12-31  3:50         ` Emanuel Berg
     [not found]         ` <mailman.1401.1451533833.843.help-gnu-emacs@gnu.org>
2015-12-31  5:37           ` Pascal J. Bourguignon
2015-12-31  7:13             ` Emanuel Berg
2015-12-31  9:30               ` tomas
2015-12-31 17:56                 ` side effects, list sharing [was: `append' vs. `nconc'] Drew Adams
2015-12-31 19:00                   ` Emanuel Berg
2015-12-31 19:15                     ` Drew Adams
2016-01-01 13:20                       ` Emanuel Berg
2015-12-31 18:51                 ` `append' vs. `nconc' Emanuel Berg
     [not found]                 ` <mailman.1440.1451588113.843.help-gnu-emacs@gnu.org>
2016-01-01  2:53                   ` Barry Margolin
2016-01-01 13:26                     ` Emanuel Berg
     [not found]             ` <mailman.1406.1451546036.843.help-gnu-emacs@gnu.org>
2015-12-31  8:54               ` Pascal J. Bourguignon
2015-12-31  7:31           ` Teemu Likonen
2015-12-31 18:35             ` Emanuel Berg
2015-12-31 20:04               ` Teemu Likonen
2016-01-01 13:23                 ` Emanuel Berg
2016-01-01 14:02                   ` Teemu Likonen
2016-01-01 18:31                     ` Emanuel Berg
     [not found]             ` <mailman.1438.1451586967.843.help-gnu-emacs@gnu.org>
2016-01-01  6:25               ` Pascal J. Bourguignon
2016-01-01 13:31                 ` Emanuel Berg
2016-01-01 15:04                   ` Drew Adams
     [not found]     ` <mailman.1353.1451490125.843.help-gnu-emacs@gnu.org>
2015-12-30 16:18       ` Pascal J. Bourguignon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).