From: Mark H Weaver <mhw@netris.org>
To: Mike Gran <spk121@yahoo.com>
Cc: Bruce Korb <bruce.korb@gmail.com>, guile-devel@gnu.org
Subject: Re: Guile: What's wrong with this?
Date: Wed, 04 Jan 2012 12:19:00 -0500 [thread overview]
Message-ID: <87y5tnfksb.fsf@netris.org> (raw)
In-Reply-To: <1325687351.71432.YahooMailNeo@web37906.mail.mud.yahoo.com> (Mike Gran's message of "Wed, 4 Jan 2012 06:29:11 -0800 (PST)")
Mike Gran <spk121@yahoo.com> writes:
>> From: Mark H Weaver <mhw@netris.org>
>> No, `define' does not copy an object, it merely makes a new reference to
>> an existing object. This is also true in C for that matter, so this is
>> behavior is quite mainstream. For example, the following program dies
>> with SIGSEGV on most modern systems, including GNU/Linux:
>>
>> int
>> main()
>> {
>> char *y = "hello";
>> y[0] = 'a';
>> return 0;
>> }
>
>
> True, but the following also is quite mainstream
> int main()
> {
> char y[6] = "hello";
> y[0] = 'a';
> return 0;
> }
>
> C provides a way to create and initialize a mutable string.
Scheme and Guile provide ways to do that too, but that's _never_ what
`define' has done.
>> Scheme and Guile are the same as C in this respect. Earlier versions of
>> Guile didn't make a copy of the string in this case either, but it
>> lacked the mechanism to detect this error, and allowed you to modify the
>> string literal in the program text itself, which is a _very_ bad idea.
>
> It all depends on your mental model. Your saying that (define y "hello")
> attaches "hello" to y, and since "hello" is a immutable, the string y
> contains must be immutable. This is an argument based on purity, not
> utility.
If we were designing a new language, then it would at least be pertinent
to argue this point. However, this is the way `define' has _always_
worked in every variant of Scheme, and the same is true of the analogous
`set' in Lisp from the very beginning.
> If you follow that logic, then Guile is left without any shorthand
> to create and initialize a mutable string other than
>
> (define y (substring "hello" 0))
> or
> (define y (string-copy "hello"))
Guile provides all the machinery you need to define shorthand syntax if
you like, e.g:
(define-syntax-rule (define-string v s) (define v (string-copy s)))
For that matter, you could also do something like this:
(define-syntax define
(lambda (x)
(with-syntax ((orig-define #'(@ (guile) define)))
(syntax-case x ()
((_ (proc arg ...) e0 e1 ...)
#'(orig-define proc (lambda (arg ...) e0 e1 ...)))
((_ v e)
(identifier? #'v)
(if (string? (syntax->datum #'e))
#'(orig-define v (string-copy e))
#'(orig-define v e)))))))
This will change `define' (in the module where it's defined) to
automatically copy a bare string literal on the right side. Note that
this check is done at compile-time, so it can't look at the dynamic type
of an expression.
If that's not good enough and you're willing to take the efficiency hit
at runtime for _every_ use of `define', you could change `define' to
wrap the right-hand expression within a procedure call to check for
read-only strings:
(define (copy-if-string x)
(if (string? x)
(string-copy x)
x))
(define-syntax define
(lambda (x)
(with-syntax ((orig-define #'(@ (guile) define)))
(syntax-case x ()
((_ (proc arg ...) e0 e1 ...)
#'(orig-define proc (lambda (arg ...) e0 e1 ...)))
((_ v e)
#'(orig-define v (copy-if-string e)))))))
Scheme's nice handling of hygiene should make redefining `define' within
your own modules (including (guile-user)) harmless. If it doesn't,
that's a bug and we'd like to hear about it.
> It was wrong to change this without deprecating it first.
The only change here was to add the machinery to detect an error that
was _always_ an error. It _never_ did what you say that it should do.
What it did before was fail to detect that you were changing the string
constant in the program text itself. The Guile 1.8 example I gave in my
last email in this thread demonstrates that.
To make that point even clearer, I'll post the full copy of the error
message Guile 1.8 gave when my loop ran past the end of the string:
guile> (let loop ((i 0))
(define y "hello")
(display y)
(newline)
(string-set! y i #\a)
(loop (1+ i)))
hello
aello
aallo
aaalo
aaaao
aaaaa
Backtrace:
In standard input:
2: 0* [loop 0]
In unknown file:
?: 1 (letrec ((y "aaaaa")) (display y) ...)
...
?: 2 (letrec ((y "aaaaa")) (display y) ...)
In standard input:
2: 3* [string-set! "aaaaa" {5} #\a]
standard input:2:60: In procedure string-set! in expression (string-set! y i ...):
standard input:2:60: Value out of range 0 to 4: 5
ABORT: (out-of-range)
guile>
Take a look at the backtrace, where it helpfully shows you an excerpt of
the source code (admittedly after some transformation). See how the
source code itself has been modified? This is what Bruce's code does.
It was _always_ a serious error in the code, even if it went undetected
in earlier versions of Guile.
Mark
next prev parent reply other threads:[~2012-01-04 17:19 UTC|newest]
Thread overview: 117+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-03 4:08 What's wrong with this? Bruce Korb
2012-01-03 15:03 ` Mike Gran
2012-01-03 16:26 ` Guile: " Bruce Korb
2012-01-03 16:30 ` Mike Gran
2012-01-03 22:24 ` Ludovic Courtès
2012-01-03 23:15 ` Bruce Korb
2012-01-03 23:33 ` Ludovic Courtès
2012-01-04 0:55 ` Bruce Korb
2012-01-04 3:12 ` Noah Lavine
2012-01-04 17:37 ` bytevector -- was: " Bruce Korb
2012-01-04 21:17 ` Ludovic Courtès
2012-01-04 22:36 ` Bruce Korb
2012-01-05 0:01 ` Ludovic Courtès
2012-01-05 18:36 ` non-reproduction of initial issue -- was: " Bruce Korb
2012-01-05 18:50 ` Mark H Weaver
2012-01-04 12:19 ` Ian Price
2012-01-04 17:16 ` Bruce Korb
2012-01-04 17:21 ` Andy Wingo
2012-01-04 17:39 ` David Kastrup
2012-01-04 21:52 ` Ian Price
2012-01-04 22:18 ` Bruce Korb
2012-01-04 23:22 ` Mike Gran
2012-01-04 23:59 ` Mark H Weaver
2012-01-05 17:22 ` Bruce Korb
2012-01-05 18:13 ` Mark H Weaver
2012-01-05 19:02 ` Mark H Weaver
2012-01-05 20:24 ` David Kastrup
2012-01-05 22:42 ` Mark H Weaver
2012-01-06 1:02 ` Mike Gran
2012-01-06 1:41 ` Mark H Weaver
2012-01-06 2:38 ` Noah Lavine
2012-01-06 13:37 ` Mike Gran
2012-01-06 14:11 ` David Kastrup
2012-01-06 18:13 ` Mark H Weaver
2012-01-06 19:06 ` Bruce Korb
2012-01-06 19:19 ` David Kastrup
2012-01-06 20:03 ` Mark H Weaver
2012-01-07 16:13 ` Mark H Weaver
2012-01-07 17:35 ` mutable interfaces - was: " Bruce Korb
2012-01-07 17:47 ` David Kastrup
2012-01-07 18:30 ` Mark H Weaver
2012-01-07 18:55 ` Mark H Weaver
2012-01-06 22:23 ` Guile BUG: " Bruce Korb
2012-01-06 23:11 ` Mark H Weaver
2012-01-06 23:35 ` Andy Wingo
2012-01-06 23:41 ` Bruce Korb
2012-01-07 15:00 ` Mark H Weaver
2012-01-07 15:27 ` Bruce Korb
2012-01-07 16:38 ` Mark H Weaver
2012-01-07 17:39 ` Bruce Korb
2012-01-09 15:41 ` Mark H Weaver
2012-01-09 17:27 ` Bruce Korb
2012-01-09 18:32 ` Andy Wingo
2012-01-09 19:48 ` Bruce Korb
2012-01-07 15:47 ` David Kastrup
2012-01-07 17:07 ` Mark H Weaver
2012-01-07 14:35 ` Mark H Weaver
2012-01-07 15:20 ` Mike Gran
2012-01-07 22:25 ` Ludovic Courtès
2012-01-10 9:13 ` The empty string and other empty strings Ludovic Courtès
2012-01-10 11:28 ` Mike Gran
2012-01-10 13:03 ` Mark H Weaver
2012-01-10 13:09 ` Mike Gran
2012-01-10 15:41 ` Mark H Weaver
2012-01-10 15:48 ` David Kastrup
2012-01-10 16:15 ` Mark H Weaver
2012-01-12 22:33 ` Ludovic Courtès
2012-01-13 9:27 ` David Kastrup
2012-01-13 16:39 ` Mark H Weaver
2012-01-13 17:36 ` David Kastrup
2012-01-16 8:26 ` Marijn
2012-01-16 8:47 ` David Kastrup
2012-01-20 21:31 ` Andy Wingo
2012-01-10 14:10 ` David Kastrup
2012-01-10 12:21 ` Mike Gran
2012-01-10 12:27 ` Mark H Weaver
2012-01-10 16:34 ` Ludovic Courtès
2012-01-10 17:04 ` David Kastrup
2012-01-06 23:28 ` Guile BUG: What's wrong with this? Bruce Korb
2012-01-07 20:57 ` Guile: " Ian Price
2012-01-08 5:05 ` Mark H Weaver
2012-01-06 9:23 ` David Kastrup
2012-01-05 7:22 ` David Kastrup
2012-01-04 22:46 ` Ludovic Courtès
2012-01-04 3:04 ` Mike Gran
2012-01-04 9:35 ` nalaginrut
2012-01-04 9:41 ` David Kastrup
2012-01-04 21:07 ` Ludovic Courtès
2012-01-04 10:03 ` Mark H Weaver
2012-01-04 14:29 ` Mike Gran
2012-01-04 14:45 ` David Kastrup
2012-01-04 16:47 ` Andy Wingo
2012-01-04 17:14 ` David Kastrup
2012-01-04 17:32 ` Andy Wingo
2012-01-04 17:49 ` David Kastrup
2012-01-04 18:09 ` Andy Wingo
2012-01-04 17:30 ` Bruce Korb
2012-01-04 17:44 ` David Kastrup
2012-01-04 18:26 ` Ian Price
2012-01-04 18:48 ` Mark H Weaver
2012-01-04 19:29 ` Bruce Korb
2012-01-04 20:20 ` David Kastrup
2012-01-04 23:19 ` Mark H Weaver
2012-01-04 23:28 ` Bruce Korb
2012-01-07 15:43 ` Fixed string corruption bugs (was Guile: What's wrong with this?) Mark H Weaver
2012-01-07 16:19 ` Fixed string corruption bugs Andy Wingo
2012-01-04 18:31 ` Guile: What's wrong with this? Mark H Weaver
2012-01-04 18:43 ` Andy Wingo
2012-01-04 19:29 ` Mark H Weaver
2012-01-04 19:43 ` Andy Wingo
2012-01-04 20:08 ` Bruce Korb
2012-01-04 20:14 ` David Kastrup
2012-01-04 20:56 ` Andy Wingo
2012-01-04 21:30 ` Bruce Korb
2012-01-04 17:19 ` Mark H Weaver [this message]
2012-01-05 4:24 ` Mark H Weaver
2012-01-04 22:37 ` Ludovic Courtès
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=87y5tnfksb.fsf@netris.org \
--to=mhw@netris.org \
--cc=bruce.korb@gmail.com \
--cc=guile-devel@gnu.org \
--cc=spk121@yahoo.com \
/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).