unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
From: Mark H Weaver <mhw@netris.org>
To: j kalbhenn <jkal@posteo.eu>
Cc: guile-user@gnu.org
Subject: Re: read syntax vectors immutable
Date: Thu, 22 Jun 2017 12:44:59 -0400	[thread overview]
Message-ID: <87a850hsz8.fsf@netris.org> (raw)
In-Reply-To: <20170622090458.GA15025@sph-desktop.fritz.box> (j. kalbhenn's message of "Thu, 22 Jun 2017 09:04:58 +0000")

j kalbhenn <jkal@posteo.eu> writes:

> vectors created using read syntax are apparently immutable with guile 2.2.2:
>
> --
> (define a #(0))
> (if (vector? a) (vector-set! a 0 1))
>
> In procedure vector-set!: Wrong type argument in position 1 (expecting mutable vector): #(0)
> --
>
> is this documented somewhere in the guile manual or part of the scheme standard? i could not find anything about it.

R5RS section 4.1.2 (Literal expressions) states:

     As noted in section *note Storage model::, it is an error to alter
     a constant (i.e.  the value of a literal expression) using a
     mutation procedure like 'set-car!' or 'string-set!'.

Also, if you look up 'quote' in the Guile index, it says:

     Note that an application must not attempt to modify literal lists
     or vectors obtained from a ‘quote’ form, since they may be in
     read-only memory.

Although only a few types are listed above, in fact it is an error to
mutate *any* literal, regardless of its type.

In Scheme, it has always been the case that literals are supposed to be
immutable.  However, earlier versions of Guile failed to detect improper
attempts to mutate literals in most cases, and yet doing so would lead
to unspecified and often very confusing behavior.

Literals are, in effect, part of the code itself, and successfully
mutating them typically has the effect of modifying the code itself.

For example, suppose you write a procedure that returns a vector of all
zeroes, but with a '1' at a given index.  Improperly mutating vector
literals, you might try this:

  GNU Guile 2.0.11
  Copyright (C) 1995-2014 Free Software Foundation, Inc.
  
  Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
  This program is free software, and you are welcome to redistribute it
  under certain conditions; type `,show c' for details.
  
  Enter `,help' for help.
  scheme@(guile-user)> (define (mask n)
                         (let ((v '#(0 0 0 0 0 0 0 0)))
                           (vector-set! v n 1)
                           v))
  scheme@(guile-user)> (mask 3)
  $1 = #(0 0 0 1 0 0 0 0)

So far, so good.  Now let's try some other values:

  scheme@(guile-user)> (mask 6)
  $2 = #(0 0 0 1 0 0 1 0)
  scheme@(guile-user)> (mask 0)
  $3 = #(1 0 0 1 0 0 1 0)

See, you're modifying the code.  Let's disassemble 'mask' to look at its
compiled code:

  scheme@(guile-user)> ,x mask
  Disassembly of #<procedure mask (n)>:
  
     0    (assert-nargs-ee/locals 1)      ;; 1 arg, 0 locals
     2    (object-ref 1)                  ;; #(1 0 0 1 0 0 1 0) at (unknown file):2:32
     4    (local-ref 0)                   ;; `n'
     6    (make-int8:1)                   ;; 1
     7    (vector-set)                                          at (unknown file):3:25
     8    (object-ref 1)                  ;; #(1 0 0 1 0 0 1 0) at (unknown file):2:32
    10    (return)                        

And indeed, the code has been modified.

To create a mutable vector, use 'vector', or apply 'vector-copy' to a
literal vector.  Also note that these are shallow copies, e.g. if you
have nested vector literals, 'vector-copy' will only copy the top layer.

       Mark



  reply	other threads:[~2017-06-22 16:44 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-22  9:04 read syntax vectors immutable j kalbhenn
2017-06-22 16:44 ` Mark H Weaver [this message]
2017-06-22 16:57   ` Mark H Weaver
2017-06-23  9:24   ` j kalbhenn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87a850hsz8.fsf@netris.org \
    --to=mhw@netris.org \
    --cc=guile-user@gnu.org \
    --cc=jkal@posteo.eu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).