Re: GNU Guile 3.0.10 released

2024-06-24 Thread Linus Björnstam
What a wonderful release! High fives all around!

Since I got a other kid I have only really done 2 things, a little bit of goof 
loop (https://git.sr.ht/~bjoli/goof-loop) and the patch to make define valid in 
more situations. I didn't even know it was merged, but I am glad I was able to 
contribute something :)

Best regards
  Linus Björnstam

On Sun, 23 Jun 2024, at 23:56, Andy Wingo wrote:
> We are pleased to announce GNU Guile release 3.0.10, the latest in the
> 3.0 stable release series.
>
> Guile 3.0.10 is a bug-fix release which also adds optimizations, support
> for a new WebAssembly back-end, new custom port facilities, a new
> optional front-end syntax, and more.  See the NEWS extract at the end of
> the mail for full details.
>
> Here are the compressed sources:
>   ftp://ftp.gnu.org/gnu/guile/guile-3.0.10.tar.gz   (9.3MB)
>   ftp://ftp.gnu.org/gnu/guile/guile-3.0.10.tar.lz   (5.3MB)
>   ftp://ftp.gnu.org/gnu/guile/guile-3.0.10.tar.xz   (5.6MB)
>
> Here are the GPG detached signatures:
>   ftp://ftp.gnu.org/gnu/guile/guile-3.0.10.tar.gz.sig
>   ftp://ftp.gnu.org/gnu/guile/guile-3.0.10.tar.lz.sig
>   ftp://ftp.gnu.org/gnu/guile/guile-3.0.10.tar.xz.sig
>
> Use a mirror for higher download bandwidth:
>   https://www.gnu.org/order/ftp.html
>
> Here are the SHA1 and SHA256 checksums:
>
> ca52ff876b8552b6f8f70231cc33ef7cbcc4a95f  guile-3.0.10.tar.gz
> Lb28l1mLL68xATVk77SOT+1EEx0o6ZbCar6KWyO1bCo  guile-3.0.10.tar.gz
> 105a99a0771d7371502b529b762abe18d729930e  guile-3.0.10.tar.lz
> 8Nl8zPUG5LYQTFFjm9G3v2dADgs0AfCy9rcTZTIEAyc  guile-3.0.10.tar.lz
> e95e37f681dae692de52242929cbc7092eef3eb4  guile-3.0.10.tar.xz
> vXFoUX/VJjM0RtT3q4FlJ5JWNAlPvTcyLhfiuNjnY4g  guile-3.0.10.tar.xz
>
> The SHA256 checksum is base64 encoded, instead of the
> hexadecimal encoding that most checksum tools default to.
>
> Use a .sig file to verify that the corresponding file (without the
> .sig suffix) is intact.  First, be sure to download both the .sig file
> and the corresponding tarball.  Then, run a command like this:
>
>   gpg --verify guile-3.0.10.tar.gz.sig
>
> The signature should match the fingerprint of the following key:
>
>   pub   rsa4096 2017-08-09 [SC]
> 4FD4 D288 D445 934E 0A14  F9A5 A880 3732 E443 6885
>   uid   Andy Wingo 
>   uid   Andy Wingo 
>   uid   Andy Wingo 
>
> If that command fails because you don't have the required public key,
> or that public key has expired, try the following commands to retrieve
> or refresh it, and then rerun the 'gpg --verify' command.
>
>   gpg --recv-keys 4FD4D288D445934E0A14F9A5A8803732E4436885
>
> As a last resort to find the key, you can try the official GNU
> keyring:
>
>   wget -q https://ftp.gnu.org/gnu/gnu-keyring.gpg
>   gpg --keyring gnu-keyring.gpg --verify guile-3.0.10.tar.gz.sig
>
>
> This release was bootstrapped with the following tools:
>   Autoconf 2.71
>   Automake 1.16.5
>   Libtool 2.4.7
>   Gnulib v0.1-4855-g8f4538a53d
>   Makeinfo 7.1
>
> An extract from NEWS follows.
>
>
> * Notable changes
>
> ** Beginnings of support for alternate back-ends
>
> A number of adaptations and additions of as-yet unstable interfaces have
> been made to allow third-party projects such as the Hoot
> Guile-to-WebAssembly whole-program compiler
> (https://spritely.institute/hoot/) to use the Guile front-end and
> optimizer.  Depending on how Hoot development goes, we may consider
> adding first-class support for WebAssembly as a compilation target;
> discussion is welcome on the guile-devel mailing list.
>
> ** `define` in all bodies
>
> `define` adds a definition to the body in which it appears, as if each
> non-tail definition or expression in that body were a binding in a
> surrounding `letrec*` clause.  However, in some places, using `define`
> would result in the annoying error "definition in expression context,
> where definitions are not allowed", which could be fixed by explicitly
> adding a surrounding binding contour, for example an empty `let`.  This
> was because there was no implicit surrounding lexical binding contour
> for the body of `when` and `unless`, for `cond` clauses, `case` clauses,
> `and-let*` bodies, and `with-fluids`.  But no more; now these contexts
> now create a binding contour, allowing the use of `define`.
>
> ** Two bug fixes of note regarding scoping of top-level variables
>
> Previously, a reference to a top-level variable in a module other than
> the current module would be silently rewritten to reference the current
> module, if the variable was unbound in its original module.  This was a
> hack from the early days of when we extended psyntax to know about the
> module system, and is now fixed to properl

Re: Inconsistency with expressions between definitions

2023-09-25 Thread Linus Björnstam
Hi again!

I am not sure about letrec*, but this should really raise an error in r6rs. You 
cannot reference a variable before it is assigned. 

I said it "would work in racket" because I believe it uses the same algorithm 
for deciding when and how and where and how and when things are bound in 
letrec*. This should also be the case in chez, but chez displays an error. 
Given I have found the chez is never wrong with regards to R6RS we can say that 
guiles behaviour is not conformant with r6rs. 

It is also inconsistent with regards to guiles manual, at least if the part on 
internal definitions is to be believed. 

What I am saying is: congrats, you found a bug :)

Sorry about confusing you. I was never really sure about letrec* behaviour, but 
you nerdsniped me and I spent some time reading the "fixing letrec (reloaded)" 
paper, and now things are more clear.

-- 
  Linus Björnstam

On Sun, 24 Sep 2023, at 18:02, Dr. Arne Babenhauserheide wrote:
> Hi,
>
> Linus Björnstam  writes:
>
>> When you are not referencing x before defining y everything works as
>> you want. There is no, so to say, temporal dependency on how the
>> things are bound. When you introduce (display x) before actually
>> defining y you force letrec* to bind x to the unspecified value,
>> because display has side-effects and you don't move around
>> side-effecting code.
>
> This is a technical explanation. It answers "how does this happen?"
> (thank you for that!), but not "why is this the correct behavior?".
>
> The core problem I see: if you inject some logging code between the
> defines, the behavior changes.
>
> I would expect that referencing a variable that can’t yet be used in an
> intermediate expression (between defines) would not cause a (potentially
> subtle) behavior change, but would throw an error: variable used in
> expression that depends on later define.
>
> Racket does not support defines using later defines at all:
>
> $ racket
>> (define (using-later-variable)
>>  (define x y)
>>  (define y #t)
>>  x)
>> (using-later-variable)
> y: undefined;
>  cannot use before initialization
>  [,bt for context]
>
> Best wishes,
> Arne
> -- 
> Unpolitisch sein
> heißt politisch sein,
> ohne es zu merken.
> draketo.de
>
> Attachments:
> * signature.asc



Re: Inconsistency with expressions between definitions

2023-09-24 Thread Linus Björnstam

Hey!

When you are not referencing x before defining y everything works as you 
want. There is no, so to say, temporal dependency on how the things are 
bound. When you introduce (display x) before actually defining y you 
force letrec* to bind x to the unspecified value, because display has 
side-effects and you don't move around side-effecting code.


If you do (display "heippa!") instead it works as you want.

I believe racket (which does the same optimization) has the same behaviour.

-- Linus Björnstam

Den 2023-09-24 kl. 09:09, skrev Dr. Arne Babenhauserheide:

Hi,

while writing a comment to SRFI-245 I think I found an inconsistency in
the Implementation in Guile.

This works:

(define (using-later-variable)
   (define x y)
   (define y #t)
   x)
(using-later-variable)
;; => #t

This still works:

(define (using-later-variable)
   (define x y)
   (newline)
   (define y #t)
   x)
(using-later-variable)
;; => (newline output)
;; => #t

This fails:

(define (using-later-variable)
   (define x y)
   (display x)
   (newline)
   (define y #t)
   x)
(using-later-variable)
;; => #

Best wishes,
Arne




Re: [PATCHv3] Extensions for SRFI-171 (Transducers)

2023-08-12 Thread Linus Björnstam
Hi!

I have finally started getting some computer time again, and I will make sure 
to get this into some kind of extra library in the official SRFI repo. 

It will not be official, but maybe for a future SRFI based on SRFI 171.
 

-- 
  Linus Björnstam

On Wed, 28 Jun 2023, at 14:27, Colin Woodbury wrote:
> Hi again, any thoughts on these SRFI-171 extensions?
>
> On 5/18/23 09:36, Colin Woodbury wrote:
>> Hi! Forgive the delay; my copyright assignment for Guile has finally 
>> gone through. Please let me know if the patches are still good!
>>
>> Colin
>>
>> On 1/24/23 18:07, Ludovic Courtès wrote:
>>> Hi Colin,
>>>
>>> Colin Woodbury  skribis:
>>>
>>>> Sorry if I wasn't clear - I have alright assigned copyright to the FSF
>>>> (about 1.5 years ago). Things should be good to go, unless I've
>>>> misunderstood.
>>> I checked the records on fencepost.gnu.org and AFAICS, you assigned
>>> copyright for Emacs only (copyright assignments are for a single GNU
>>> package), so you will need to do the paperwork for Guile this time.
>>>
>>> Thanks in advance.  :-)
>>>
>>> Ludo’.



Re: Clojure support

2023-05-07 Thread Linus Björnstam
http://wingolog.org/pub/fash.scm

-- 
  Linus Björnstam

On Sat, 4 Mar 2023, at 12:22, Philip McGrath wrote:
> On Sat, Mar 4, 2023, at 5:28 AM, Linus Björnstam wrote:
>> Andy already has a fast implementation of functional hashtables 
>> ("fash") which are of a particular high quality. They do not support 
>> element removal which should be trivial to add.  Other than that it has 
>> all the basic functionality needed to build a complex library on top. 
>
> I’ve heard a few people mention “fash”, but I haven’t managed to find 
> the code: could you give a link?
>
> -Philip



Re: Functional datatypes in Guile

2023-03-05 Thread Linus Björnstam
On Sat, 4 Mar 2023, at 17:38, pukkamustard wrote:
> Hi Dave,
>
> Makes me wonder, are Andy Wingo's fash/fector purely functional? Why do
> they need atomic boxes? Aren't they only necessary for destructive
> updates?

This is to make sure that transient-fectors/flashes (in-place mutation with 
some copying going on to not break the other copies of the sector being 
mutated) thread safe. They should only be mutated by the current thread. 

It is a nice trade off , since you get a lot less copying if you mutate many 
values in the same leaf. This is especially good when building a fector meaning 
you can fill every tail by just using vector-set! without copying. Let's just 
say that it becomes a lot faster:)

/Linus 



Re: Clojure support

2023-03-04 Thread Linus Björnstam
Regarding data structures, there are some additions that should be made to the 
standard clojure versions. There would be no reason to implement a regular 
leftwise-dense persistent vector when there is something like RRB-trees 
available, which provide no slowdown compared to the leftwise dense vectors 
when used as such, but can "degrade" to RRB-trees when needed as a means to 
support amortized O(1) concatenation, insertion, and splitting. 

If a C library is to be used, C-rrb is a very high quality implementation. I 
tried to implement RRB-trees in guile, but I never quite got the merge 
algorithm to work as it should. Scalas functional vectors are RRB-trees with 
some really cool additions to the tail optimization.

Andy already has a fast implementation of functional hashtables ("fash") which 
are of a particular high quality. They do not support element removal which 
should be trivial to add.  Other than that it has all the basic functionality 
needed to build a complex library on top. 

-- 
  Linus Björnstam

On Tue, 28 Feb 2023, at 18:03, Lassi Kortela wrote:
>> I've been thinking how it'd be nice to have available in Guile a number of
>> purely functional datatypes, these being hashmaps, vectors, and sets.
>
> Those are core data types of Clojure. It'd be nice if the canonical 
> Scheme versions of these types have Clojure-compatible semantics. This 
> will make it easy to turn Scheme implementations into partial 
> implementations of Clojure. This is already being attempted in Lokke 
> (https://github.com/lokke-org/lokke).



Re: Add internal definitions to derived forms

2023-01-25 Thread Linus Björnstam


On Wed, 25 Jan 2023, at 16:38, Greg Troxel wrote:

> My reaction, without thinking much, and being fuzzy on a lot of things
> is that part of the point of guile is that it is Scheme which to me
> means RnRS conformance.   Of course it's not exactly and every other
> Scheme impl is not exactly.  But mostly I think that's a bug as it leads
> to incompatible programs.

Guile already has some nonstandard syntax extensions. Definitions in expression 
context in some places (all bodies, just not begin), cond extensions etc. I had 


> Does the new feature advance the goal of guile as an extension language?

It makes guile more approachable for beginners. We have all written convoluted 
cond clauses that could have been a lot clearer with internal definitions.

> Is this heading for inclusino in the next RnRS?

No, but...

bodies are now specified using letrec*. Allowing internal definitions is a 
small step away, but the only one I heard mentioning it was Marc. I suspect 
they are moving carefully.

The reason r5rs did not include it was that bodies were specified in terms of 
letrec. That made internal definitions hard to pin down. 

Best regards 
Linus 



Re: Add internal definitions to derived forms

2023-01-25 Thread Linus Björnstam



On Wed, 25 Jan 2023, at 16:09, Ludovic Courtès wrote:
> Hello!
>
> Linus Björnstam  skribis:
>
>
> Daniel pushed this as 764e3614b8c13de604399572a67d071621e9ca21 in
> ‘main’.  I had completely overlooked this thread but I wasn’t quite sure
> about it, so I did not include it in 3.0.9.
>
> The reason I’m hesitant is that, while I think it’s nice to be able to
> have local ‘define’ in these contexts, I’m wary of diverging from R5RS
> and R6RS.  Since it’s a one-way change (we won’t be able to revert it
> once people rely on it), I thought we’d rather be careful.

Andy gave a similar idea thumbs up in IRC some time ago. We could always make 
r6rs cond, case etc. use (begin ...). For that we could just re-use the example 
implementations from the r6rs appendix depending on license.

R5RS compatibility is a harder but to crack. Maybe a compat library like r6rs 
has?

/Linus



Re: Add internal definitions to derived forms

2023-01-23 Thread Linus Björnstam
Hi!

Sorry about the delay, I have an updated patch somewhere, but I started working 
after 4 months paternity leave and family life's fortunes has it so that I 
haven't used a computer since the last time I wrote an email in this thread 
(this is written on a phone).

This is likely how will be in the foreseeable future, despite me having bought 
an analog keyboard to turn into some kind of music instrument :)

For what it is worth:

The body ... was taken from and-let* and the newer patch was changed to follow 
the description of let. And "lambda-like body" was changed to "let-expression 
body".

I will not have the ability to address anything nor actually send my updates 
patch for what is probably months. If anyone wants to take over I would be 
happy. For what it is worth, I have already signed a copyright assignment to 
the FSF. 

Best regards
  Linus Björnstam (manumanumanu)

On Tue, 24 Jan 2023, at 00:28, lloda wrote:
> Hi Ludovic,
>
>> On 23 Jan 2023, at 23:13, Ludovic Courtès  wrote:
>> 
>> Hi Daniel,
>> 
>> Chiming in late in the discussion…
>> 
>> lloda  skribis:
>> 
>>> From 7aea299373f7370f31c9701035260ad412763724 Mon Sep 17 00:00:00 2001
>>> From: Daniel Llorens 
>>> Date: Thu, 19 Jan 2023 16:23:29 +0100
>>> Subject: [PATCH 2/2] Fix documentation for forms taking lambda-like bodies
>>> 
>>> * doc/ref/api-control.texi (Conditionals): Use 'body' in the syntax
>>>  description of when, unless, cond, case.
>>> * doc/ref/api-binding.texi (Local Bindings): Normalize description of
>>>  body return values.
>>>  (Multiple values): Normalize use of 'body' and description of body
>>>  return values.
>> 
>> What about:
>> s/Fix documentation…/doc: Document multiple-value returns in let, cond, etc./
>> ?
>> 
>> (That would clarify what’s being fixed.)
>
> Ok.
>
>> 
>>> +++ b/doc/ref/api-binding.texi
>>> @@ -128,6 +128,8 @@ expressions has a few properties which are well worth 
>>> knowing.
>>> 
>>> The most basic local binding construct is @code{let}.
>>> 
>>> +@cindex body
>> 
>> That’s not a great index entry because there’s no context.  Maybe:
>> 
>>  @cindex body, of a @code{let} expression
>> 
>> ?
>
> Ok. I think the word is only used in this sense in the manual, but it 
> might too generic to be used alone.
>
>>> +with the special forms @code{when} and @code{unless}.  As an added
>>> +bonus, these forms take a @ref{Local Bindings,lambda-like body}, which can
>>> +contain @ref{Internal Definitions,internal definitions} and multiple 
>>> statements
>>> +to evaluate.
>> 
>> “Lambda-like body” is not defined; I guess it’s “lambda-like” in the
>> wrt. to local ‘define’, but it’s not “lambda-like” for the more crucial
>> aspect of defining a procedure, so I’d avoid that phrase.  WDYT?
>
> Yes, I thought lambda-like was a tad distracting, so I went with 'body' 
> alone...
>
>> Also, @ref in the middle of sentences may render poorly in Info (info
>> "(texinfo) @ref").  I’d suggest “(@pxref{Whatever})” at the end of the
>> sentence or proposition.
>
> Ok.
>
>>> Each @code{cond}-clause must look like this:
>>> 
>>> @lisp
>>> -(@var{test} @var{body} @dots{})
>>> +(@var{test} @var{body})
>> 
>> I think removing dots is incorrect here because it suggests, according
>> to the typographic conventions used in the document, that there can only
>> be a single expression.
>> 
>>> @var{key} may be any expression, and the @var{clause}s must have the form
>>> 
>>> @lisp
>>> -((@var{datum1} @dots{}) @var{body} @dots{})
>>> +((@var{datum1} @dots{}) @var{body})
>> 
>> Ditto.
>> 
>>> and the last @var{clause} may have the form
>>> 
>>> @lisp
>>> -(else @var{expr1} @var{body} @dots{})
>>> +(else @var{body})
>> 
>> Ditto.
>> 
>>> -@deffn {library syntax} receive formals expr body @dots{}
>>> +@deffn {library syntax} receive formals expr body
>> 
>> Likewise.
>
> This was actually the main thing I wanted to fix in this patch. Linus' 
> patch had ‘body ...’ but that clearly means ‘zero or more bodies’, 
> which doesn't work because there's exactly one ‘body’. I.e. ‘body’ 
> isn't an expression that is tagged ‘body’, it's, well, a ‘body’.
>
> The Scheme reports use one ‘’ and no dots in all these 
> definitions. See also the definition of let in the linked section 
> ‘Local Bindings’, which again uses ‘body’ and no dots. I hoped that 
> section would count as definition of ‘body’, and the section on 
> ‘Internal Definitions’ explains precisely what can go into ‘body’, so I 
> linked to that as well. I see that isn't clear enough. Maybe ‘body’ 
> should be explicitly defined in one of these sections?
>
>> Otherwise LGTM; it’s certainly an improvement to have multiple-value
>> returns properly documented!
>> 
>> Thanks,
>> Ludo’.



Re: [PATCH] Extensions for SRFI-171 (Transducers)

2022-12-21 Thread Linus Björnstam
As the author of both the SRFI and the guile code I am very happy you like it. 
I don't have a computer at the moment, but I looked through the code and it 
looked great.

All additions should have been included in the original SRFI :)

one comment: your code uses define-public, which the rest of SRFI-171 code does 
not.

I am not in any position to sign code off for inclusion in guile proper, but if 
the define-public thing is fixed it very much has my blessing.

Best regards 
  Linus Björnstam

On Wed, 21 Dec 2022, at 01:48, Colin Woodbury wrote:
> Happy holidays everyone, I hope everything is going well for you.
>
> Since discovering SRFI-171 (Transducers) I have fallen in love with it. 
> Transducers let me "talk the way I want to talk" while knowing that I'm 
> being efficient underneath w.r.t. to iteration and allocation. In using 
> Guile's implementation, I noticed a few common idioms missing that are 
> otherwise present in other languages, so I've added them in a series of 
> patches. I've been using these often for a number of weeks without 
> issue, but of course have added unit tests as well.
>
> The full details are in the commit messages, but here are the main highlights:
>
>  * rfold: The fundamental reducer. This allows the user to turn any 
> two-arg function into a valid reducer, so that they don't need to worry 
> about hand-writing reducers via case-lambda. 
>  * rfind: Yields the first item in the transduction that matches some 
> predicate. Nice for locating some specific value from a potentially 
> large data source (e.g. a port). 
>  * twindow: Like tsegment, but yields overlapping slices into the data. 
> Cheers, and have a great holiday.
>
> Colin
>
> Attachments:
> * 0001-srfi-171-add-twindow-and-various-reducers.patch
> * 0002-doc-add-new-SRFI-171-reducers-to-the-manual.patch
> * 0003-srfi-171-add-unit-tests-for-new-functions.patch



Re: Add internal definitions to derived forms

2022-11-18 Thread Linus Björnstam
On Fri, 18 Nov 2022, at 11:22, Lassi Kortela wrote:
> R7RS defines the syntax of `let` et.al. as follows (section 3.5):
>
> (let (*) )
>
> Where:
>
>  = * 
>  = * 
>
> So their definition of lambda:
>
> (lambda  * * )
>
> could be abbreviated:
>
> (lambda  )
>
> I haven't read "Fixing letrec" but it looks like Guile intents to 
> redefine  as follows:
>
>  = * 
> * =  | 
>
> R6RS appears to use  in the same sense as R7RS.

That is a better way to write it indeed. clause-body being equal to a lambda 
body. 

Thank you.



Re: Add internal definitions to derived forms

2022-11-18 Thread Linus Björnstam
On Fri, 18 Nov 2022, at 10:27, Lassi Kortela wrote:
>> Would "is like the body of a lambda" be a better wording?
>
> R7RS section 3.5. says:
>
> (lambda  * * )
>
> The * are the stuff you are adding.

Not quite. Guile extends the lambda body (and by extension let-forms) to allow 
mixed definitions and expressions:

(lambda () 
  (display "Heippa!")
  (define routsi #t)
  (and (read) routsi))

which expands to, more or less, a letrec*. All in accordance to the paper 
fixing letrec(reloaded).

Thus saying that the cond clause body is like a lambda body is probably the 
simplest way to express it. 

best regards
Linus Björnstam



Re: Add internal definitions to derived forms

2022-11-18 Thread Linus Björnstam
Hi!

Well, the point of the change is to make it so that things other than 
expressions are allowed. I change it to say @var{body}, and then later clarify 
that @var{test} is an arbitrary expression and @var{body} is a lambda-like 
body. 

Which when reading it now sounds... not very good. 

Would "is like the body of a lambda" be a better wording? That would imply that 
at least one expression is required. English is very much not my first 
language, and documentation changes are the ones that I fear the most...

best regards
  Linus Björnstam

On Thu, 17 Nov 2022, at 08:25, lloda wrote:
> Hi Linus,
>
> I don't understand the following change since at least one expression 
> is required in these clauses.
>
>  @lisp
>  (@var{test} => @var{expression})
> @@ -217,7 +217,7 @@ result of the @code{cond}-expression.
>  @var{key} may be any expression, and the @var{clause}s must have the form
> 
>  @lisp
> -((@var{datum1} @dots{}) @var{expr1} @var{expr2} @dots{})
> +((@var{datum1} @dots{}) @var{body} @dots{})
>  @end lisp
>
> Regards
>
>   Daniel



Add internal definitions to derived forms

2022-11-09 Thread Linus Björnstam
Hi there!

This commit adds internal definitions to derived conditional forms, with-fluids 
and and-let*. This means the bodies of when, unless and with-fluids, and the 
clause bodies of case and cond behave like a lambda body. 

There is no performance hit since guile optimizes a (let () ...) without 
internal definitions to a begin (i.e: no new lexical context is created).

best regards
  Linus BjörnstamFrom 7eeb91b822334b151c5b4a15ce9528a2a655d914 Mon Sep 17 00:00:00 2001
From: Linus 
Date: Wed, 9 Nov 2022 16:15:18 +0100
Subject: [PATCH] Add internal definitions to derived forms

This commit adds internal definitions to the following derived
forms: when, unless, cond, case, with-fluids, and and-let*.

 * doc/ref/api-control.texi (Conditionals): Update the syntax and docs
   of when, unless, cond, and case.
 * module/ice-9/and-let-star.scm (and-let*): Changed begins to let.
 * module/ice-9/boot-9.scm (cond, case, when, unless, with-fluids):
   Changed begins to let.
---
 doc/ref/api-control.texi  | 25 +
 module/ice-9/and-let-star.scm |  6 +++---
 module/ice-9/boot-9.scm   | 12 ++--
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/doc/ref/api-control.texi b/doc/ref/api-control.texi
index 087e795..ece6a60 100644
--- a/doc/ref/api-control.texi
+++ b/doc/ref/api-control.texi
@@ -152,10 +152,10 @@ documentation:
 
 @example
 (define-syntax-rule (when test stmt stmt* ...)
-  (if test (begin stmt stmt* ...)))
+  (if test (let () stmt stmt* ...)))
 
 (define-syntax-rule (unless test stmt stmt* ...)
-  (if (not test) (begin stmt stmt* ...)))
+  (if (not test) (let () stmt stmt* ...)))
 @end example
 
 That is to say, @code{when} evaluates its consequent statements in order
@@ -167,11 +167,11 @@ statements if @var{test} is false.
 Each @code{cond}-clause must look like this:
 
 @lisp
-(@var{test} @var{expression} @dots{})
+(@var{test} @var{body} @dots{})
 @end lisp
 
-where @var{test} and @var{expression} are arbitrary expressions, or like
-this
+where @var{test} is an arbitrary expression and @var{body} is a
+lambda-like body, or like this
 
 @lisp
 (@var{test} => @var{expression})
@@ -217,7 +217,7 @@ result of the @code{cond}-expression.
 @var{key} may be any expression, and the @var{clause}s must have the form
 
 @lisp
-((@var{datum1} @dots{}) @var{expr1} @var{expr2} @dots{})
+((@var{datum1} @dots{}) @var{body} @dots{})
 @end lisp
 
 or
@@ -229,7 +229,7 @@ or
 and the last @var{clause} may have the form
 
 @lisp
-(else @var{expr1} @var{expr2} @dots{})
+(else @var{expr1} @var{body} @dots{})
 @end lisp
 
 or
@@ -239,13 +239,14 @@ or
 @end lisp
 
 All @var{datum}s must be distinct.  First, @var{key} is evaluated.  The
-result of this evaluation is compared against all @var{datum} values using
-@code{eqv?}.  When this comparison succeeds, the expression(s) following
-the @var{datum} are evaluated from left to right, returning the value of
-the last expression as the result of the @code{case} expression.
+result of this evaluation is compared against all @var{datum} values
+using @code{eqv?}.  When this comparison succeeds, the @var{body}
+following the @var{datum} is evaluated like the body of a lambda,
+returning the value of the last expression as the result of the
+@code{case} expression.
 
 If the @var{key} matches no @var{datum} and there is an
-@code{else}-clause, the expressions following the @code{else} are
+@code{else}-clause, the @var{body} following the @code{else} is
 evaluated.  If there is no such clause, the result of the expression is
 unspecified.
 
diff --git a/module/ice-9/and-let-star.scm b/module/ice-9/and-let-star.scm
index 2d53ff3..9427c17 100644
--- a/module/ice-9/and-let-star.scm
+++ b/module/ice-9/and-let-star.scm
@@ -53,12 +53,12 @@
   ((_ orig-form ((var expr)) . body)
(identifier? #'var)
#'(let ((var expr))
-   (and var (begin . body
+   (and var (let () . body
   ((_ orig-form ((expr)) . body)
-   #'(and expr (begin . body)))
+   #'(and expr (let () . body)))
   ((_ orig-form (var) . body)
(identifier? #'var)
-   #'(and var (begin . body)))
+   #'(and var (let () . body)))
 
   ;; Handle bad clauses.
   ((_ orig-form (bad-clause . rest) . body)
diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index a46145e..dc35370 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -417,10 +417,10 @@ If returning early, return the return value of F."
 (include-from-path "ice-9/quasisyntax")
 
 (define-syntax-rule (when test stmt stmt* ...)
-  (if test (begin stmt stmt* ...)))
+  (if test (let () stmt stmt* ...)))
 
 (define-syntax-rule (unless test stmt stmt* ...)
-  (if (not test) (begin stmt stmt* ...)))
+  (if (not test) (let () stmt stmt* ...)))
 
 (define-syntax else
   (lambda (x)
@@ -461,7 +461,7 @@ If returning early, return the return value of F."
  ((else e e* ...)
   (lambd

Re: expression and definition context in Scheme

2022-08-30 Thread Linus Björnstam
I am working on a patch to guile to add definitions to just about every body 
except for (begin ...) outside definition context.

The patch is trivial, but I have to document it and a patch to r6rs that makes 
the r6rs cons work according to spec.

I had a kid recently so it might take some time before I have any computer 
time, so if anyone has some time this is a really simple thing. You can find 
the first patch somewhere in this mailing list, it only changes the (begin 
...)s in the derived forms in (ice-9 boot-9) to (let () ...). Then i was going 
to copy the cond and case from the r6rs appendix and add some error reporting.

The most difficult part is documenting it :)

Andy have the idea hos blessing, and will mean guile gets define in expression 
context in when, unless, cond, case, while, and do as well as in derived forms.

-- 
  Linus Björnstam

On Sat, 27 Aug 2022, at 18:48, Damien Mattei wrote:
> Hello,
>
> i'm facing sometimes recursively the problem to have definitions in 
> expression context, which i manage every time by adding an upper empty 
> (let () my definitions goes here )
> the last case i was facing this probleme is defining a 'for macro:
>
> ;; scheme@(guile-user)> (for ({i <+ 0} {i < 5} {i <- {i + 1}}) (display 
> i) (newline))
> ;; 0
> ;; 1
> ;; 2
> ;; 3
> ;; 4
>
>
> (define-syntax for
>  
>   (syntax-rules ()
>
> ((_ (init test incrmt) b1 ...)
>
>(let ()
>init
>(let loop ()
>   (when test
> b1 ...
> incrmt
> (loop)))
>
> this one fails in my Scheme+ code below:
> (define (compute-carries n)
>
>   (for ( {k <+ 0}  {k <= n}  {k <- {k + 1}} )
>
>{ Ckp1 <+ (compute-Ck-plus1 k) }
>(display-nl Ckp1)))
>
> because { Ckp1 <+ (compute-Ck-plus1 k) } expands in :
> (define Ckp1 (compute-Ck-plus1 k))
> and i get a compilation error:
> ;;; Syntax error:
> ;;; logic-syracuse+.scm:15:7: definition in expression context, where 
> definitions are not allowed, in form (define Ckp1 (compute-Ck-plus1 k))
>
> so i replace my 'for macro definition with:
>
> (define-syntax for
>  
>   (syntax-rules ()
>
> ((_ (init test incrmt) b1 ...)
>
>(let ()
>init
>(let loop ()
>   (when test
> (let ()
> b1 ...
> incrmt
> (loop
>
> and it works, but you will notice an abusive use of empty (let () ...) 
> in the code to avoid the restrictions of definitions not allowed in 
> expression context. 
>
> My ideas is as it is so easy to cheat the compiler from seeing the 
> expressio context why does the compiler restrict this? expression and 
> defintion context, i'm not sure they are in scheme standarts, are they 
> really usefull?
> why not remove this from Scheme at all?
>
> Regards,
>
> Damien



Re: Hatables are slow

2022-02-22 Thread Linus Björnstam
Hej!

I would also propose a hash table based on a more sane interface. The equality 
and hash procedures should be associated with the hash table at creation rather 
than every time the hash table is used. Like in R6RS, srfi-69, or srfi-12X 
(intermediate hash tables). 

Maybe the current HT could be relegated to some kind of compat or deprecated 
library to be removed in 3.4... I am no maintainer, but I think we can all 
agree that the current API, while fine in the context of guile 1.6, is somewhat 
clunky by today's standards. It is also commonplace enough that regular 
deprecation might become rough.

Just the simple fact that hash-set! and hashq-set! can be used interchangeably 
while you at the same time NEVER EVER should mix them is somewhat unnerving.

I would say a hash table that specifies everything at creation time (with maybe 
an opportunity to use something like the hashx-* functions for daredevils and 
for future srfi needs) is the way to go.

Best regards
  Linus Björnstam

On Mon, 21 Feb 2022, at 14:18, Stefan Israelsson Tampe wrote:
> A datastructure I fancy is hash tables. But I found out that hashtables 
> in guile are really slow, How? First of all we make a hash table
>
> (define h (make-hash-table))
>
> Then add values
> (for-each (lambda (i) (hash-set! h i i)) (iota 2000))
>
> Then the following operation cost say 5s
> (hash-fold (lambda (k v s) (+ k v s)) 0 h)
>
> It is possible with the foreign interface to speedt this up to 2s using 
> guiles internal interface. But this is slow for such a simple 
> application. Now let's change focus. Assume the in stead an assoc,
>
> (define l (map (lambda (i) (cons i i)) (iota 2000)))
>
> Then
> ime (let lp ((l ll) (s 0)) (if (pair? l) (lp (cdr l) (+ s (caar l))) s)) 
> $5 = 1999000 
> ;; 0.114530s real time, 0.114391s run time.  0.00s spent in GC.
>
> That's 20X faster. What have happened?, Well hashmaps has terrible 
> memory layout for scanning. So essentially keeping a list of the 
> created values consed on a list not only get you an ordered hashmap, 
> you also have 20X increase in speed, you sacrifice memory, say about 
> 25-50% extra. The problem actually more that when you remove elements 
> updating the ordered list is very expensive. In python-on-guile I have 
> solved this by moving to a doubly linked list when people start's to 
> delete single elements. For small hashmap things are different.
>
> I suggest that guile should have a proper faster standard hashmap 
> implemention of such kind in scheme.
>
> Stefan



Re: Fwd: [Patch] definitions in when, unless, do as well as in cond- and case-clauses

2022-02-06 Thread Linus Björnstam
Historical garage maybe. I just remember some old bug in WebKit where let was a 
lot slower than var because it created what was called lexical context which 
affected interpreter speed because of some kind of linear time variable lookup.

Anyway, that stuff doesn't apply to guile versions after 2. Especially since a 
(let () body ...) where the body contains no (define ...) gets converted to a 
(begin body ...) by the optimizer. 

The behaviour of begin Vs let is well specified and any begin outside of a body 
context is just chain of expressions. It just lacks internal definitions. 

-- 
  Linus Björnstam

On Sun, 6 Feb 2022, at 21:13, Stefan Israelsson Tampe wrote:
> Hmm just why conditionals use begin and not let,
>
> On Sun, Feb 6, 2022 at 11:49 AM  wrote:
>> On Sun, Feb 06, 2022 at 10:45:54AM +0100, Linus Björnstam wrote:
>> > You need to use ,optimize. 
>> 
>> Thanks you both, Maxime and Linus, for giving me a new lantern :)
>> 
>> Cheers
>> -- 
>> t



Re: Fwd: [Patch] definitions in when, unless, do as well as in cond- and case-clauses

2022-02-06 Thread Linus Björnstam
You need to use ,optimize. 

-- 
  Linus Björnstam

On Sun, 6 Feb 2022, at 10:27, to...@tuxteam.de wrote:
> On Sun, Feb 06, 2022 at 07:44:31AM +0100, Linus Björnstam wrote:
>> 
>> On Sat, 5 Feb 2022, at 18:31, Stefan Israelsson Tampe wrote:
>> > Hmm this was wrong, I mean
>> >
>> > For conditional variables we have a default begin. So then why on earth 
>> > do you not have an implicit let?, Just laziness?
>> > There should  be a good reason or? this is a pretty fundamental change 
>> > that I support but then we should not be lazy not trying to understand 
>> > the design choices of the old beards.
>> 
>> In other languages let starts a new lexical context which can be expensive. 
>> I don't know guile internals but a let without any defines is trivially 
>> converted to a begin by the optimizer.
>
> It seems that in Guile 3 the expander is smart enough for an empty
> bindings list in let:
>
> | tomas@trotzki:~$ guile
> | GNU Guile 3.0.7.6-22120
> | Copyright (C) 1995-2021 Free Software Foundation, Inc.
>
> [...]
>
> | scheme@(guile-user)> ,expand (let () (message #t "Yikes"))
> | $1 = (message #t "Yikes")
> | scheme@(guile-user)> ,expand (let ((x 3)) (message #t "Yikes ~S" x))
> | $2 = (let ((x 3)) (message #t "Yikes ~S" x))
>
> ...but doesn't "see" whether bindings are actually used (quite possibly
> those go away in a later optimisation phase, though):
>
> | scheme@(guile-user)> ,expand (let ((x 3)) (message #t "Yikes"))
> | $3 = (let ((x 3)) (message #t "Yikes"))
>
> Cheers
> -- 
> t
>
> Attachments:
> * signature.asc



Re: Fwd: [Patch] definitions in when, unless, do as well as in cond- and case-clauses

2022-02-05 Thread Linus Björnstam


On Sat, 5 Feb 2022, at 18:31, Stefan Israelsson Tampe wrote:
> Hmm this was wrong, I mean
>
> For conditional variables we have a default begin. So then why on earth 
> do you not have an implicit let?, Just laziness?
> There should  be a good reason or? this is a pretty fundamental change 
> that I support but then we should not be lazy not trying to understand 
> the design choices of the old beards.

In other languages let starts a new lexical context which can be expensive. I 
don't know guile internals but a let without any defines is trivially converted 
to a begin by the optimizer.






Re: [Patch] definitions in when, unless, do as well as in cond- and case-clauses

2022-02-03 Thread Linus Björnstam
Hi guys,

It looks like a 3.0.8 might be happening. I am curious to know whether this 
(perhaps minus the do form) is considered something that the maintainers of 
guile could find interesting. 

If subset compatibility of r6|7rs is desired, I could provide a patch for those 
files as well so that they enforce the distinction between definition and 
expression context.

I myself find this a worthwhile patch since it has no drawbacks. a (let () ...) 
without definitions does not start a new lexical context and runs as fast as a 
begin, so there should be no performance regressions.

It also removes the last bodies in guile forms that have a definition context, 
which may be confusing for beginners.

I would say that the compatibility question with the enforcing cond of rnrs is 
the only thing that needs proper addressing.

Best
  Linus Björnstam

On Wed, 16 Jun 2021, at 21:11, Linus Björnstam wrote:
> Hi there!
>
> This patch updates some derived conditional forms (and do and and-let*) 
> to support definitions in expression context. Meaning it makes this 
> valid code:
>
> (cond 
>   ((pred? arg) 
> (define a (something arg))
> (when (error-case a)
>   (error "a is broken"))
> (define b (something2 a))
> (when  (= 3 *log-level*)
>   (display "logging something1 and 2 as successful"))
> (define c (something3 b a))
> (when (odd? c)
>(error "something went wrong in something3"))
> c)
>   (else 
> ;;chosen by fair dice roll. Guaranteed to be random
> 4)))
>
> While awful, is sometimes what the world makes us do. 
>
> The change means cond, case, when and unless behaves like it does in 
> racket. Do was below case, so I changed that as well, and will actually 
> become yet another way guile is superior to racket. 
>
> I did also change the documentation, but I learned english by watching 
> Beverly Hills cop, so that might need some fine touches by a capable 
> english speaker.
>
>
> Best regards
>   Linus Björnstam
> Attachments:
> * 0001-Allow-definitions-in-derived-conditional-forms.patch



Re: Scheme+

2021-12-20 Thread Linus Björnstam
Hi Damien!

I played around with it and it seems to rely heavily on mutation, which makes 
guile (and chez and racket for that matter) box the values. That adds a layer 
of indirection to memory access, meaning slower code (apart from the more 
obvious problems of continuation safety and threading safety). It could be 
partially fixed with a very much not fun to write syntax case macro: you expand 
a body as far as possible into a letrec* (and letrec-syntax) shadowing bindings 
when needed and use set! only in places where bindings are not declared. 

The workhorse you need for that is syntax-local-binding.

 If you want this system to be resilient and work well with other scheme code 
that is probably the path to go. One could imagining having a procedure form 
that is fully expanded, analyzed and then some-kind-of-CPS-transformed so that 
all variables are passed as state. That way you would get continuation and 
thread safety, while allowing something that seems like and, at least locally, 
behaves like mutation to take place. 

This (the local mutation part) is tangential to something I have wanted to 
write for a long time, but I have not had the time (nor intelligence). If you 
want to discuss some ideas or have any question we can take this off-list.

Another thing would be to not use call/cc in the def form. Let/ec is a lot 
faster.

-- 
  Linus Björnstam

On Mon, 20 Dec 2021, at 01:05, Damien Mattei wrote:
> Hi,
> I finished today the first version of Scheme+.
> Scheme+ is an extension of the syntax of the Scheme language.
> Scheme+ makes it easy the assignment of Scheme objects in infix (works also
> in prefix) notation with a few new operators  ← (or  <-), [ ],⥆ (or <+) .
>
> Scheme+ does much more things,see:
>
> https://damien-mattei.github.io/Scheme-PLUS-for-Guile/Scheme+io.html
>
> or:
>
> https://github.com/damien-mattei/Scheme-PLUS-for-Guile/blob/main/README.md
>
> static light HTML page:
> https://damien-mattei.github.io/Scheme-PLUS-for-Guile/Scheme+.html
>
> direct link to code and README:
> https://github.com/damien-mattei/Scheme-PLUS-for-Guile
>
> Best regards,
>
> Damien Mattei



Re: guile and libgccjit

2021-10-10 Thread Linus Björnstam
The the current JIT is, in my understanding, more or less a stepping stone 
towards native compilation. The current JIT is very small and lightweight, 
without any tracing, meaning things like register allocation is flexible going 
forward.

I am not a maintainer, nor heavily involved, but I believe libgccjit would be a 
step sideways considering the above. 

Best regards
  Linus Björnstam

On Sun, 10 Oct 2021, at 01:06, Andy Tai wrote:
> can guile make use of libgccjit?
>
> would be an interesting optional addition to guile



Re: [Patch] definitions in when, unless, do as well as in cond- and case-clauses

2021-06-17 Thread Linus Björnstam
Guile already does definitions in expression context in the bodies of lambda 
and let-variants. I think this is not a big problem since any valid r6rs code 
is still valid guile.

The discussion is in my opinion whether guile's r6rs modules should enforce 
this behaviour. That might be a good thing, even though we will provide 2 cons 
and case forms to do that.

-- 
  Linus Björnstam

On Thu, 17 Jun 2021, at 11:06, Maxime Devos wrote:
> Linus Björnstam schreef op wo 16-06-2021 om 21:11 [+0200]:
> > Hi there!
> > 
> > This patch updates some derived conditional forms (and do and and-let*)
> > to support definitions in expression context. Meaning it makes this valid 
> > code:
> > 
> > (cond 
> >   ((pred? arg) 
> > (define a (something arg))
> > (when (error-case a)
> >   (error "a is broken"))  [...]
> 
> This seems a useful change to me. However, this is not valid R6RS.
> From <http://www.r6rs.org/final/r6rs.pdf>:
> 
> (cond hcond clause1i hcond clause2i . . . ) syntax
> => auxiliary syntax
> else auxiliary syntax
> Syntax: Each hcond clausei must be of the form
> (htesti hexpression1i . . . )
> where htesti is an expression. Alternatively, a
> hcond clausei may be of the form
> (htesti => hexpressioni)
> 
> This seems a compatibility pitfall, so maybe note
> in the documentation that using definitions in the clauses
> is a Guile and Racket extension and not standard R6RS?
> 
> (I try to write Scheme code as R6RS / R7RS library & define-library
> forms, importing mostly R6RS / R7RS & SRFI libraries, though I occasionally
> use a Guile extension.)
> 
> Greetings,
> Maxime
> 
> Attachments:
> * signature.asc



[Patch] definitions in when, unless, do as well as in cond- and case-clauses

2021-06-16 Thread Linus Björnstam
Hi there!

This patch updates some derived conditional forms (and do and and-let*) to 
support definitions in expression context. Meaning it makes this valid code:

(cond 
  ((pred? arg) 
(define a (something arg))
(when (error-case a)
  (error "a is broken"))
(define b (something2 a))
(when  (= 3 *log-level*)
  (display "logging something1 and 2 as successful"))
(define c (something3 b a))
(when (odd? c)
   (error "something went wrong in something3"))
c)
  (else 
;;chosen by fair dice roll. Guaranteed to be random
4)))

While awful, is sometimes what the world makes us do. 

The change means cond, case, when and unless behaves like it does in racket. Do 
was below case, so I changed that as well, and will actually become yet another 
way guile is superior to racket. 

I did also change the documentation, but I learned english by watching Beverly 
Hills cop, so that might need some fine touches by a capable english speaker.


Best regards
  Linus BjörnstamFrom 7af96162bf531b70e66170864cd536032b1c89c7 Mon Sep 17 00:00:00 2001
From: Linus 
Date: Wed, 16 Jun 2021 20:47:41 +0200
Subject: [PATCH] Allow definitions in derived conditional forms

This allows definitions in the bodies of when, unless, do, and
 and-let*. It also adds support for definitions in cond- and
case-clauses.

 * doc/ref/api-control.texi (when, unless, cond, case): update
   documentation to reflect changes.
 * module/ice-9/and-let-star.scm: Changed (begin ...) to (let () ...)
 * module/ice-9/boot-9.scm (when, unless, cond, case, do): changed
   (begin ...) to (let () ...)
---
 doc/ref/api-control.texi  | 10 +-
 module/ice-9/and-let-star.scm |  6 +++---
 module/ice-9/boot-9.scm   | 12 ++--
 3 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/doc/ref/api-control.texi b/doc/ref/api-control.texi
index 5df5344c5..eaa2b4dbf 100644
--- a/doc/ref/api-control.texi
+++ b/doc/ref/api-control.texi
@@ -152,10 +152,10 @@ documentation:
 
 @example
 (define-syntax-rule (when test stmt stmt* ...)
-  (if test (begin stmt stmt* ...)))
+  (if test (let () stmt stmt* ...)))
 
 (define-syntax-rule (unless condition stmt stmt* ...)
-  (if (not test) (begin stmt stmt* ...)))
+  (if (not test) (let () stmt stmt* ...)))
 @end example
 
 That is to say, @code{when} evaluates its consequent statements in order
@@ -167,11 +167,11 @@ statements if @var{test} is false.
 Each @code{cond}-clause must look like this:
 
 @lisp
-(@var{test} @var{expression} @dots{})
+(@var{test} @var{expression-or-definition} @dots{})
 @end lisp
 
-where @var{test} and @var{expression} are arbitrary expressions, or like
-this
+where @var{test} is an arbitrary expression, and @var{expression-or-definition}
+is an arbitrary expression or a definition, like @code{define}.
 
 @lisp
 (@var{test} => @var{expression})
diff --git a/module/ice-9/and-let-star.scm b/module/ice-9/and-let-star.scm
index 2d53ff384..9427c1733 100644
--- a/module/ice-9/and-let-star.scm
+++ b/module/ice-9/and-let-star.scm
@@ -53,12 +53,12 @@
   ((_ orig-form ((var expr)) . body)
(identifier? #'var)
#'(let ((var expr))
-   (and var (begin . body
+   (and var (let () . body
   ((_ orig-form ((expr)) . body)
-   #'(and expr (begin . body)))
+   #'(and expr (let () . body)))
   ((_ orig-form (var) . body)
(identifier? #'var)
-   #'(and var (begin . body)))
+   #'(and var (let () . body)))
 
   ;; Handle bad clauses.
   ((_ orig-form (bad-clause . rest) . body)
diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index 2323b1ec5..675f38633 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -417,10 +417,10 @@ If returning early, return the return value of F."
 (include-from-path "ice-9/quasisyntax")
 
 (define-syntax-rule (when test stmt stmt* ...)
-  (if test (begin stmt stmt* ...)))
+  (if test (let () stmt stmt* ...)))
 
 (define-syntax-rule (unless test stmt stmt* ...)
-  (if (not test) (begin stmt stmt* ...)))
+  (if (not test) (let () stmt stmt* ...)))
 
 (define-syntax else
   (lambda (x)
@@ -461,7 +461,7 @@ If returning early, return the return value of F."
  ((else e e* ...)
   (lambda (tail)
 (if (null? tail)
-#'((begin e e* ...))
+#'((let () e e* ...))
 (bad-clause "else must be the last clause"
  ((else . _) (bad-clause))
  ((test => receiver)
@@ -488,7 +488,7 @@ If returning early, return the return value of F."
  ((test e e* ...)
   (lambda (tail)
 #`((if test
-   (begin e e* ...)
+   (let () e e* ...)
#,@tail
   

Re: Python-on-guile

2021-04-23 Thread Linus Björnstam
Hurra!

I noticed a couple.of weeks ago that declarative modules made it possible for 
me to stop using define-syntax-rule to force stupid inlining of code. The cross 
module inlining branch will make that even nicer. I can write cleaner code and 
get better error messages :)

Guile has been going in a very nice direction for some time!
-- 
  Linus Björnstam

On Fri, 23 Apr 2021, at 17:00, Mikael Djurfeldt wrote:
> Hi,
> 
> Yesterday, Andy committed new code to the compiler, some of which 
> concerned skipping some arity checking.
> 
> Also, Stefan meanwhile committed something called "reworked object 
> system" to his python-on-guile.
> 
> Sorry for coming with unspecific information (don't have time to track 
> down the details) but I noticed that my benchmark script written in 
> Python, and which computes the 20:th Ramanujan number, now runs 60% 
> faster than before these changes.
> 
> This means that python-on-guile running on guile3 master executes 
> python code only 2.6 times slower than the CPython python3 interpreter 
> itself. :-)
> 
> Have a nice weekend all,
> Mikael
> 



Re: [PATCH] add SRFI: srfi-121; generators

2021-04-10 Thread Linus Björnstam
Hi Arthur!

I have been looking for the code, seemingly in vain. I had a disk failure not 
too long ago, and it was probably in one directory not backed up. I will keep 
looking for it, since I am still in some kind of low-effort journey to restore 
my home directory, but I don't think I will find anything. 

I still want to write an implementation of srfi-158 for guile, but given the 
current state I believe it is quite far in the future. I have had a bout 2 
hours of serious computer time per week since the new year with no end to this 
horrible draught in sight!

I will let you know if I find anything.

-- 
  Linus Björnstam

On Thu, 8 Apr 2021, at 17:53, Arthur A. Gleckler wrote:
> On Tue, Jan 26, 2021 at 3:54 AM Linus Björnstam 
>  wrote:
> > The code's internet presence is apparently gone (bitbucket mercurial. I 
> > don't know how I missed that ). I won't have access to that code for about 
> > 2 weeks, but I will upload it and try to get it up to par with the updated 
> > SRFI-158. 
> 
> Hi, Linus.  Have you had a chance to do this?
> 
> Thanks.



Re: Guile Potluck 2021

2021-03-01 Thread Linus Björnstam
Hi Guilers!

I found some code I wrote while drunk. I had completely forgotten about it, but 
found it a fun little exercise. I would argue that falls under the "neglected 
library" category.

Anyway: It implements python-style generators, with yield and, more 
importantly, yield-from:

https://git.sr.ht/~bjoli/awesome-coroutine-generators

I tried to extend it while sober. It didn't work, so be warned  I guess. The 
code is somewhat a mess, but short enough to be understandable.
Best regards
  Linus Björnstam

On Thu, 18 Feb 2021, at 18:24, Mike Gran wrote:
> Hello All-
> 
> In celebration of the (slightly belated) 10-year anniversary of Guile
> v2.0, we're having another Guile Potluck!  The Guile Potluck is a
> randomly annual event to give people a chance to show off their Guile
> projects and skills.  Think of it as a game jam, but, not constrained
> to games. 
> 
> To participate, on or before Mar 6, send an email to guile-u...@gnu.org
> with instructions on how to find your entry, which could be anything
> you like.  For example,
> 
>- a script showing off some feature of Guile or your favorite Guile
>library
>- a blog post describing something interesting about Guile
>- an updated release of a neglected library
>- a mini-game
>- a graphical or audio demoscene-type demo
>
> There probably won't be any prizes.  But there will definitely be an e-
> mail and blog post about the entries.
> 
> If you think you might attempt to participate, please reply to this e-
> mail so I can gauge the feasibility of some sort of participation swag.
> 
> Regards,
> Mike Gran, on behalf of the Guile team
> 
> 
> 
>



Re: Guile Potluck 2021

2021-02-27 Thread Linus Björnstam
I had a look and there is quite a lot you can do. Just out of curiosity: how 
much is GC time? You are generating a lot of intermediate data. Instead of 
vector-append! maybe use something like the new vectorlist srfi? If you show me 
a flame graph and give me some test data I can have a go!

-- 
  Linus Björnstam

On Sat, 27 Feb 2021, at 10:39, Dr. Arne Babenhauserheide wrote:
> I’d like to contribute a basic implementation of the Web of Trust in
> Freenet that provides spam-detection without centralized control:
> 
> https://hg.sr.ht/~arnebab/wispwot/browse/wispwot/wispwot.scm
> 
> Currently this takes 70s to calculate aggregated trust scores on 300k
> trust edges.
> 
> I hope to get this faster and would love if someone would want to try
> to golf its runtime down :-)
> 
> Best wishes,
> Arne
> 
> Mike Gran  writes:
> 
> > On Fri, 2021-02-26 at 15:19 -0800, Aleix Conchillo Flaqué wrote:
> >> In case it was not clear:
> >> 
> >> guile-oauth 1.0.0 with OAuth2 support: 
> >> https://github.com/aconchillo/guile-oauth
> >> guile-redis 2.1.0 with Redis 6.2.0 commands:
> >> https://github.com/aconchillo/guile-redis
> >> 
> >> Aleix
> >> 
> >
> > Awesome. Thanks! Look forward to checking it out.
> >
> >> On Sun, Feb 21, 2021 at 9:59 PM Aleix Conchillo Flaqué
> >>  wrote:
> >> > 
> >> > Thank you Mike!
> >> > 
> >> > I should have waited to release guile-oauth with the OAuth2 support
> >> > :-). But if that counts...
> >> > 
> >> > Also planning to release guile-redis with redis 6.2 support when
> >> > they make a release (they are in RC3), but I might do it sooner.
> >> > 
> >> > Best,
> >> > 
> >> > Aleix
> >> > 
> >> > On Thu, Feb 18, 2021, 9:43 AM Mike Gran  wrote:
> >> > > 
> >> > > Hello All-
> >> > > 
> >> > > In celebration of the (slightly belated) 10-year anniversary of
> >> > > Guile
> >> > > v2.0, we're having another Guile Potluck!  The Guile Potluck is a
> >> > > randomly annual event to give people a chance to show off their
> >> > > Guile
> >> > > projects and skills.  Think of it as a game jam, but, not
> >> > > constrained
> >> > > to games.
> >> > > 
> >> > > To participate, on or before Mar 6, send an email to 
> >> > > guile-u...@gnu.org
> >> > > with instructions on how to find your entry, which could be
> >> > > anything
> >> > > you like.  For example,
> >> > > 
> >> > >- a script showing off some feature of Guile or your favorite
> >> > > Guile
> >> > >library
> >> > >- a blog post describing something interesting about Guile
> >> > >- an updated release of a neglected library
> >> > >- a mini-game
> >> > >- a graphical or audio demoscene-type demo
> >> > > 
> >> > > There probably won't be any prizes.  But there will definitely be
> >> > > an e-
> >> > > mail and blog post about the entries.
> >> > > 
> >> > > If you think you might attempt to participate, please reply to
> >> > > this e-
> >> > > mail so I can gauge the feasibility of some sort of participation
> >> > > swag.
> >> > > 
> >> > > Regards,
> >> > > Mike Gran, on behalf of the Guile team
> >> > > 
> >> > > 
> >> > > 
> 
> 
> -- 
> Unpolitisch sein
> heißt politisch sein
> ohne es zu merken
> 
> Attachments:
> * signature.asc



Re: [PATCH] Make vector-map and vector-for-each in (rnrs base) fast

2021-02-19 Thread Linus Björnstam
As suspected: the eq? optimization does nothing.

I will write some tests for (r6rs base) to test the multi-vector behaviour of 
this. Currently only (vector-map proc vec1) is tested in there. That comes 
whenever I get my next computer time. It might be weeks, though.

Also regarding (r6rs base): the two maps in guile seem compatible: (ice-9 
boot-9) and (rnrs base) map both seem to have the same limitations (only proper 
lists of the same length), but the boot-9 one seems faster with worse error 
messages - probably due to some offloading to C. 

Wouldn't one definition be a better choice, and if so: which one? 
-- 
  Linus Björnstam

On Thu, 18 Feb 2021, at 08:34, Linus Björnstam wrote:
> Hi there!
> 
> I was spelunking through the guile source tree and found (rnrs base). 
> The vector-map and vector-for-each in there are horribly inefficient. 
> They are doing (list->vector (apply map PROC (map vector->list 
> vectors))), which means it spends quite some time checking for circular 
> references.
> 
> This fixes that. The speedup is surprisingly small, considering we pass 
> through the elements 2 fewer times and don't chase pointers through 
> memory trying to find cycles. Anywhere from 30 to 300% depending on how 
> the stars are aligned on things like (vector-map + vec vec)
> 
> One potential speedup we could do is using eq? to compare numbers, but 
> I don't know how well fixnums in guile overlap size_t, regardless of 
> how realistic such a limitation would be. If I change the behaviour of 
> vector-map to go back-to-front (order is unspecified in r6rs) we can 
> easily do (eq? -1 index) as a stop condition to avoid any eventual 
> overhead of type checking with =. (If those are not elided, which I 
> suspect might be the case. ). I did not look at that, since I have too 
> little computer time these days.
> 
> As an added bonus, this speeds up quicksort.scm in ecraven's benchmarks 
> by a little.
> -- 
>   Linus Björnstam
> Attachments:
> * 0001-Write-a-proper-vector-map-and-vector-for-each-for-rn.patch



[PATCH] Make vector-map and vector-for-each in (rnrs base) fast

2021-02-17 Thread Linus Björnstam
Hi there!

I was spelunking through the guile source tree and found (rnrs base). The 
vector-map and vector-for-each in there are horribly inefficient. They are 
doing (list->vector (apply map PROC (map vector->list vectors))), which means 
it spends quite some time checking for circular references.

This fixes that. The speedup is surprisingly small, considering we pass through 
the elements 2 fewer times and don't chase pointers through memory trying to 
find cycles. Anywhere from 30 to 300% depending on how the stars are aligned on 
things like (vector-map + vec vec)

One potential speedup we could do is using eq? to compare numbers, but I don't 
know how well fixnums in guile overlap size_t, regardless of how realistic such 
a limitation would be. If I change the behaviour of vector-map to go 
back-to-front (order is unspecified in r6rs) we can easily do (eq? -1 index) as 
a stop condition to avoid any eventual overhead of type checking with =. (If 
those are not elided, which I suspect might be the case. ). I did not look at 
that, since I have too little computer time these days.

As an added bonus, this speeds up quicksort.scm in ecraven's benchmarks by a 
little.
-- 
  Linus BjörnstamFrom 6dc71eeec1b0efad9be23c6f72323cdc58caf26b Mon Sep 17 00:00:00 2001
From: Linus 
Date: Wed, 17 Feb 2021 22:28:19 +0100
Subject: [PATCH] Write a proper vector-map and vector-for-each for (rnrs base)

 * module/rnrs/base.scm (vector-map vector-for-each): Rewrite to not be slow.
---
 module/rnrs/base.scm | 80 +---
 1 file changed, 76 insertions(+), 4 deletions(-)

diff --git a/module/rnrs/base.scm b/module/rnrs/base.scm
index 9205016bd..cd2327e49 100644
--- a/module/rnrs/base.scm
+++ b/module/rnrs/base.scm
@@ -231,10 +231,82 @@
(and (rational-valued? x)
 (= x (floor (real-part x)
 
- (define (vector-for-each proc . vecs)
-   (apply for-each (cons proc (map vector->list vecs
- (define (vector-map proc . vecs)
-   (list->vector (apply map (cons proc (map vector->list vecs)
+ ;; Auxiliary procedure for vector-map and vector-for-each
+ (define (vector-lengths who . vs)
+  (let ((lengths (map vector-length vs)))
+(unless (apply = lengths)
+  (apply error
+ (string-append (symbol->string who)
+": Vectors of uneven length.")
+ vs))
+(car lengths)))
+
+(define vector-map
+  (case-lambda
+"(vector-map f vec2 vec2 ...) -> vector
+
+Return a new vector of the size of the vector arguments, which
+must be of equal length. Each element at index @var{i} of the new 
+vector is mapped from the old vectors by @code{(f (vector-ref vec1 i)
+(vector-ref vec2 i) ...)}.  The dynamic order of application of 
+@var{f} is unspecified."
+((f v)
+ (let* ((len (vector-length v))
+(result (make-vector len)))
+   (let loop ((i 0))
+ (unless (= i len)
+   (vector-set! result i (f (vector-ref v i)))
+   (loop (+ i 1
+   result))
+((f v1 v2)
+ (let* ((len (vector-lengths 'vector-map v1 v2))
+(result (make-vector len)))
+   (let loop ((i 0))
+ (unless (= i len)
+   (vector-set! result
+i
+(f (vector-ref v1 i) (vector-ref v2 i)))
+   (loop (+ i 1)))
+ result)))
+((f v . vs)
+ (let* ((vs (cons v vs))
+(len (apply vector-lengths 'vector-map vs))
+(result (make-vector len)))
+   (let loop ((i 0))
+ (unless (= i len)
+   (vector-set! result
+i
+(apply f (map (lambda (v) (vector-ref v i)) vs)))
+   (loop (+ i 1
+   result
+
+(define vector-for-each
+  (case-lambda
+"(vector-for-each f vec1 vec2 ...) -> unspecified
+
+Call @code{(f (vector-ref vec1 i) (vector-ref vec2 i) ...)} for each index
+ in the provided vectors, which have to be of equal length. The iteration
+is strictly left-to-right."
+((f v)
+ (let ((len (vector-length v)))
+   (let loop ((i 0))
+ (unless (= i len)
+   (f (vector-ref v i))
+   (loop (+ i 1))
+((f v1 v2)
+ (let ((len (vector-lengths 'vector-for-each v1 v2)))
+   (let loop ((i 0))
+ (unless (= i len)
+   (f (vector-ref v1 i) (vector-ref v2 i))
+   (loop (+ i 1))
+((f v . vs)
+ (let* ((vs (cons v vs))
+(len (apply vector-lengths 'vector-for-each vs)))
+   (let loop ((i 0))
+ (unless (= i len)
+   (apply f (map (lambda (v) (vector-ref v i)) vs))
+   (loop (+ i 1
+
 
  (define-syntax define-proxy
(syntax-rules (@)
-- 
2.25.1



Re: [PATCH] add SRFI: srfi-121; generators

2021-01-26 Thread Linus Björnstam
The code's internet presence is apparently gone (bitbucket mercurial. I don't 
know how I missed that ). I won't have access to that code for about 2 weeks, 
but I will upload it and try to get it up to par with the updated SRFI-158.

Lg. Linus Björnstam

On Tue, 26 Jan 2021, at 08:14, Marc Nieper-Wißkirchen wrote:
> Am Di., 26. Jan. 2021 um 08:08 Uhr schrieb Linus Björnstam 
> :
> > Hi Y'all!
> > 
> > I have an efficient, almost done implementation of srfi-121. I believe it 
> > lacks generator-unfold, but that is all. make-coroutine-generator is 
> > implemented using delimited continuations and runs a lot faster than the 
> > one in the reference implementation, with the caveat that it is apparently 
> > slightly incompatible: the coroutine generator usage in (srfi 146 hash) 
> > yielded the wrong result - despite my version passing all tests.
> 
> Can you post a MWE?
>



Re: [PATCH] add SRFI: srfi-121; generators

2021-01-25 Thread Linus Björnstam
Sorry, I though this was in the guile mailing list.

-- 
  Linus Björnstam

On Tue, 26 Jan 2021, at 07:48, Linus Björnstam wrote:
> Hi Y'all!
> 
> I have an efficient, almost done implementation of srfi-121. I believe 
> it lacks generator-unfold, but that is all. make-coroutine-generator is 
> implemented using delimited continuations and runs a lot faster than 
> the one in the reference implementation, with the caveat that it is 
> apparently slightly incompatible: the coroutine generator usage in 
> (srfi 146 hash) yielded the wrong result - despite my version passing 
> all tests.
> 
> If the maintainers of guile are interested, I could clean this code up 
> and add accumulators and make sure it conforms to the srfi document. 
> 
> I have already spent some time integrating srfi-171 into guile, so I'm 
> not entirely unfamiliar with the task.
> 
> Best regards
>   Linus Björnstam
> 
> On Tue, 26 Jan 2021, at 04:29, John Cowan wrote:
> > Note that 121 is withdrawn, so people should implement 158.
> > 
> > On Sat, Jan 23, 2021 at 1:38 AM Mark H Weaver  wrote:
> > > Hi Arthur,
> > > 
> > > "Arthur A. Gleckler"  writes:
> > > > It's not a bad idea for the sample implementation to be as clear as
> > > > possible at the expense of performance.
> > > 
> > > I agree that it's desirable for one of the sample implementations to be
> > > as simple and clear as possible, for the purpose of clarifying the
> > > specification.
> > > 
> > > > But it certainly wouldn't hurt to have a supplemental document making
> > > > recommendations about possible performance improvements, or even a
> > > > second implementation.
> > > 
> > > Sounds good.  For SRFIs such as 121 and 158, where efficiency is
> > > important, I think that a second sample implementation tuned for
> > > performance would be a useful addition.
> > > 
> > >  Regards,
> > >Mark



Re: [PATCH] add SRFI: srfi-121; generators

2021-01-25 Thread Linus Björnstam
Hi Y'all!

I have an efficient, almost done implementation of srfi-121. I believe it lacks 
generator-unfold, but that is all. make-coroutine-generator is implemented 
using delimited continuations and runs a lot faster than the one in the 
reference implementation, with the caveat that it is apparently slightly 
incompatible: the coroutine generator usage in (srfi 146 hash) yielded the 
wrong result - despite my version passing all tests.

If the maintainers of guile are interested, I could clean this code up and add 
accumulators and make sure it conforms to the srfi document. 

I have already spent some time integrating srfi-171 into guile, so I'm not 
entirely unfamiliar with the task.

Best regards
  Linus Björnstam

On Tue, 26 Jan 2021, at 04:29, John Cowan wrote:
> Note that 121 is withdrawn, so people should implement 158.
> 
> On Sat, Jan 23, 2021 at 1:38 AM Mark H Weaver  wrote:
> > Hi Arthur,
> > 
> > "Arthur A. Gleckler"  writes:
> > > It's not a bad idea for the sample implementation to be as clear as
> > > possible at the expense of performance.
> > 
> > I agree that it's desirable for one of the sample implementations to be
> > as simple and clear as possible, for the purpose of clarifying the
> > specification.
> > 
> > > But it certainly wouldn't hurt to have a supplemental document making
> > > recommendations about possible performance improvements, or even a
> > > second implementation.
> > 
> > Sounds good.  For SRFIs such as 121 and 158, where efficiency is
> > important, I think that a second sample implementation tuned for
> > performance would be a useful addition.
> > 
> >  Regards,
> >Mark



Re: [PATCH] Add tree-il optimizations for equal? on char and number literals

2020-05-14 Thread Linus Björnstam
Works like a charm!

-- 
  Linus Björnstam

On Thu, 14 May 2020, at 10:38, Andy Wingo wrote:
> On Wed 13 May 2020 23:16, Linus Björnstam  
> writes:
> 
> > On the latest master equal? was not reduced to eq? on chars in the repl
> > for things like ,opt (define (a b) (equal? b #\b)).
> 
> This turned out to be that I had broken the REPL command.  The optimizer
> was working fine though.  Fixed now :)
> 
> Cheers,
> 
> Andy
>



Re: [PATCH] Add tree-il optimizations for equal? on char and number literals

2020-05-13 Thread Linus Björnstam
That is indeed a lot prettier!  I didn't know guile compared chars using eq? 
(The manual states that you should use eqv? For chars and numbers). 

On the latest master equal? was not reduced to eq? on chars in the repl for 
things like ,opt (define (a b) (equal? b #\b)). Was I using the new baseline 
compiler or should it always be triggered? I didn't have time to really check 
it out, and I have about a gazillion little computers that run guile. I do 
think I was sshing into the right one, though :)

Good to hear know that I can (match...) without fear in the future! Between 
this and the record unification I feel I have very little motivation to write 
my own extensible pattern matcher :) 
-- 
  Linus Björnstam

On Wed, 13 May 2020, at 15:55, Andy Wingo wrote:
> Hi :)
> 
> On Wed 13 May 2020 13:20, Linus Björnstam  
> writes:
> 
> > Hi there!
> >
> > Aleix and I noticed that equal? has a lot higher overhead than eqv? on
> > chars, which means using (ice-9 match) for chars was suboptimal. This
> > patch fixes that.
> 
> I think we can be a little more simple here.  Scheme doesn't specify
> what (eqv? #\a x) is, but in Guile it is equivalent to (eq? #\a x), and
> our compiler should be free to turn the portable eqv? invocation into
> eq?.  But as the comment on line 416 says, we should really do this in
> peval and not in the expander.  So you nerd-sniped me ;)  I just
> pushed a patch that did this.
> 
> While looking, I found this:
> 
> > + (make-conditional src (make-primcall src prim (list a b))
> > +   (make-primcall src prim (cons b rest))
> > +   (make-const src #f))
> 
> This was in the original code but is wrong: if "b" has a side-effect, it
> will happen twice.  I have fixed it in git.
> 
> Thanks for the debugging and patch!
> 
> Andy
>



[PATCH] Add tree-il optimizations for equal? on char and number literals

2020-05-13 Thread Linus Björnstam
Hi there!

Aleix and I noticed that equal? has a lot higher overhead than eqv? on chars, 
which means using (ice-9 match) for chars was suboptimal. This patch fixes that.

With this patch, guile now turns (equal? #\b var) into (eqv? #\b var) and 
(equal? any-non-fixnum-number-literal var) into (eqv? 
any-non-fixnum-number-literal var). This fixes the (ice-9 match) problem, and 
means you can dispatch to equal? in macros and guile will just do the right 
thing is there are any literals.

There is one regression: it is not o(n). Currently the primitve expander is run 
once per call, which means a (equal? #\a b c d e) becomes (and (eqv? #\a b) 
(eqv? b c d e)) and that second call gets run through the primitive expander 
once again, which checks all the arguments again. The solution I see is to 
manually build the conditional code, or to just extend the old code, where only 
the comparisons directly involving the literal is optimized: (equal? a b #\c) 
-> (and (equal? a b) (eqv? b #\c)).

Any feedback is welcome.

-- 
  Linus Björnstam

0001-Make-equal-to-eqv-or-eq-if-any-suitable-literals-are.patch
Description: Binary data


Re: Guile's time execution issues

2020-05-08 Thread Linus Björnstam
Another option would be to just overload equal? in match.scm to transform into 
eqv? when there are char literals or numbers, eq? on symbols, booleans,  the 
empty list and keywords and (@@ (guile) equal?) for everything else.

Considering that it in this case contributed a 25% overhead to code that was 
performance critical I think it would be a pretty valid thing to do. If you, 
ludo, an Andy thinks that would be a good idea I can make such a patch for 
match.scm. That would have the benefit of not changing the upstream code (which 
is (include ...)d in match.scm), nor fiddling around with guile optimisations.

-- 
  Linus Björnstam

On Mon, 4 May 2020, at 22:50, Linus Björnstam wrote:
> You didn't see my other reply. The matching code isn't suboptimal. The 
> equality predicate is  The problem is that match compares using equal? 
> even for literal chars (where eqv? is a lot faster). It would be a 
> rather trivial optimization to do, either to match.scm (meaning: 
> breaking with upstream and use syntax-case) or to the guile compiler in 
> general (changing equal? to eqv, when there are character literals), 
> which seems ok-ish for this use-case but at very little benefit in 
> general.
> 
> A long-term goal of mine is to write a pattern matcher with the 
> optimisations that the racket matcher does (among other things: some 
> serious list matching reordering!). That is a daunting task though.
> 
> -- 
>   Linus Björnstam
> 
> On Mon, 4 May 2020, at 22:09, Ludovic Courtès wrote:
> > Hi,
> > 
> > Linus Björnstam  skribis:
> > 
> > > On Mon, 4 May 2020, at 11:36, Ludovic Courtès wrote:
> > >  
> > >> > One thing I found is that `match` is slow. The code looked nicer but 
> > >> > had to change it back to lets and conds as the performance
> > >> > increase was ~2 seconds.
> > >> 
> > >> Oh, in which case exactly?  And are you sure your hand-written code is
> > >> equivalent to the ‘match’ code (it’s common for hand-written code to be
> > >> more lax than ‘match’)?
> > >> 
> > >> One thing to pay attention to is the use of ‘list?’, which is O(N), and
> > >> is implied by ellipses in ‘match’.  If you want to use ‘match’ in a way
> > >> that avoids ‘list?’, write patterns such as (a . b) instead of (a b ...).
> > >> It doesn’t have the same meaning, but often the end result is the same,
> > >> for instance because you’ll later match on ‘b’ anyway.
> > >> 
> > >> (I wish we can one day have a proper list type disjoint from pairs…)
> > >
> > > The change is here: he is only matching against chars and predicates: 
> > > https://github.com/aconchillo/guile-json/commit/ad4b06d86e4822466983d00f55474c8f664b538d
> > 
> > It would be nice if you could pinpoint which one of these changes causes
> > a difference, because:
> > 
> > --8<---cut here---start->8---
> > scheme@(guile-user)> ,optimize (match (peek-char port) ((? eof-object?) 
> > x) ((? whitespace?) w) (_ e))
> > $84 = (let ((v (peek-char port)))
> >   (cond ((eof-object? v) x)
> > ((whitespace? v) w)
> > (else e)))
> > --8<---cut here---end--->8---
> > 
> > What might make a difference is the code bloat when using ‘or’:
> > 
> > --8<---cut here---start->8---
> > scheme@(guile-user)> ,optimize (match (peek-char port) ((or #\a #\b #\c 
> > #\d) x))
> > $86 = (let ((v (peek-char port)))
> >   (cond ((equal? v #\a) x)
> > ((equal? v #\b) x)
> > ((equal? v #\c) x)
> > ((equal? v #\d) x)
> > (else
> >  ((@@ (ice-9 match) error)
> >   'match
> >   "no matching pattern"
> >   v)
> >  #f)))
> > --8<---cut here---end--->8---
> > 
> > but even that sounds unlikely.
> > 
> > You’re compiling with -O2, right?
> > 
> > Thanks,
> > Ludo’.
> >
> 
>



Re: Guile's time execution issues

2020-05-04 Thread Linus Björnstam
You didn't see my other reply. The matching code isn't suboptimal. The equality 
predicate is  The problem is that match compares using equal? even for literal 
chars (where eqv? is a lot faster). It would be a rather trivial optimization 
to do, either to match.scm (meaning: breaking with upstream and use 
syntax-case) or to the guile compiler in general (changing equal? to eqv, when 
there are character literals), which seems ok-ish for this use-case but at very 
little benefit in general.

A long-term goal of mine is to write a pattern matcher with the optimisations 
that the racket matcher does (among other things: some serious list matching 
reordering!). That is a daunting task though.

-- 
  Linus Björnstam

On Mon, 4 May 2020, at 22:09, Ludovic Courtès wrote:
> Hi,
> 
> Linus Björnstam  skribis:
> 
> > On Mon, 4 May 2020, at 11:36, Ludovic Courtès wrote:
> >  
> >> > One thing I found is that `match` is slow. The code looked nicer but had 
> >> > to change it back to lets and conds as the performance
> >> > increase was ~2 seconds.
> >> 
> >> Oh, in which case exactly?  And are you sure your hand-written code is
> >> equivalent to the ‘match’ code (it’s common for hand-written code to be
> >> more lax than ‘match’)?
> >> 
> >> One thing to pay attention to is the use of ‘list?’, which is O(N), and
> >> is implied by ellipses in ‘match’.  If you want to use ‘match’ in a way
> >> that avoids ‘list?’, write patterns such as (a . b) instead of (a b ...).
> >> It doesn’t have the same meaning, but often the end result is the same,
> >> for instance because you’ll later match on ‘b’ anyway.
> >> 
> >> (I wish we can one day have a proper list type disjoint from pairs…)
> >
> > The change is here: he is only matching against chars and predicates: 
> > https://github.com/aconchillo/guile-json/commit/ad4b06d86e4822466983d00f55474c8f664b538d
> 
> It would be nice if you could pinpoint which one of these changes causes
> a difference, because:
> 
> --8<---cut here---start->8---
> scheme@(guile-user)> ,optimize (match (peek-char port) ((? eof-object?) 
> x) ((? whitespace?) w) (_ e))
> $84 = (let ((v (peek-char port)))
>   (cond ((eof-object? v) x)
> ((whitespace? v) w)
> (else e)))
> --8<---cut here---end--->8---
> 
> What might make a difference is the code bloat when using ‘or’:
> 
> --8<---cut here---start->8---
> scheme@(guile-user)> ,optimize (match (peek-char port) ((or #\a #\b #\c #\d) 
> x))
> $86 = (let ((v (peek-char port)))
>   (cond ((equal? v #\a) x)
> ((equal? v #\b) x)
> ((equal? v #\c) x)
> ((equal? v #\d) x)
> (else
>  ((@@ (ice-9 match) error)
>   'match
>   "no matching pattern"
>   v)
>  #f)))
> --8<---cut here---end--->8---
> 
> but even that sounds unlikely.
> 
> You’re compiling with -O2, right?
> 
> Thanks,
> Ludo’.
>



Re: Guile's time execution issues

2020-05-04 Thread Linus Björnstam
Sorry, sent a premature reply. The problem is that some of those match blocks 
expand to using equal? which is a lot slower than using eqv? If we are doing it 
on every char in a 24mb file we are getting some serious constant factors. 

match is a syntax-rules macro, so distinguishing literals are not possible. 
Concerning "the macro writer's bill of rights" I could maybe think this it 
would be a rather nice thing to turn equal? to eqv? when one argument is a char 
literal :D

-- 
  Linus Björnstam

On Mon, 4 May 2020, at 11:36, Ludovic Courtès wrote:
> Hey!
> 
> Aleix Conchillo Flaqué  skribis:
> 
> > So weird I'm getting different numbers on 2.2.7. Not sure how I'm getting 
> > those initial ~20s and you are getting consistent ~ 45s. It
> > shouldn't have nothing to do with it, but could it be I'm running it on 
> > macOS?
> 
> Did you add this ‘->bool’ call to ensure the resulting alist is not kept
> in memory?
> 
> >  Now, it would be good to profile ‘json->scm’ to see if there’s anything
> >  that could be improved on the Guile side, or if it’s just a normal
> >  profile for GC-intensive code.
> >
> > Good news is that I have been working on performance improvements and 
> > json->scm is going down from my ~19 seconds to ~3
> > seconds on the same sample file. Linus Björnstam was the one to bring up 
> > performance issues so we've been back and forth trying to
> > make it fast.
> 
> Nice!
> 
> > One thing I found is that `match` is slow. The code looked nicer but had to 
> > change it back to lets and conds as the performance
> > increase was ~2 seconds.
> 
> Oh, in which case exactly?  And are you sure your hand-written code is
> equivalent to the ‘match’ code (it’s common for hand-written code to be
> more lax than ‘match’)?
> 
> One thing to pay attention to is the use of ‘list?’, which is O(N), and
> is implied by ellipses in ‘match’.  If you want to use ‘match’ in a way
> that avoids ‘list?’, write patterns such as (a . b) instead of (a b ...).
> It doesn’t have the same meaning, but often the end result is the same,
> for instance because you’ll later match on ‘b’ anyway.
> 
> (I wish we can one day have a proper list type disjoint from pairs…)
> 
> Thanks,
> Ludo’.
> 
>



Re: Guile's time execution issues

2020-05-04 Thread Linus Björnstam


On Mon, 4 May 2020, at 11:36, Ludovic Courtès wrote:
 
> > One thing I found is that `match` is slow. The code looked nicer but had to 
> > change it back to lets and conds as the performance
> > increase was ~2 seconds.
> 
> Oh, in which case exactly?  And are you sure your hand-written code is
> equivalent to the ‘match’ code (it’s common for hand-written code to be
> more lax than ‘match’)?
> 
> One thing to pay attention to is the use of ‘list?’, which is O(N), and
> is implied by ellipses in ‘match’.  If you want to use ‘match’ in a way
> that avoids ‘list?’, write patterns such as (a . b) instead of (a b ...).
> It doesn’t have the same meaning, but often the end result is the same,
> for instance because you’ll later match on ‘b’ anyway.
> 
> (I wish we can one day have a proper list type disjoint from pairs…)

The change is here: he is only matching against chars and predicates: 
https://github.com/aconchillo/guile-json/commit/ad4b06d86e4822466983d00f55474c8f664b538d




[PATCH]: Fix a documentation for SRFI-171

2020-05-01 Thread Linus Björnstam
Hi yall!

I managed to bork the documentation in my patch that added SRFI-171 to guile. 
Here is the two-line patch to fix it. 

Sorry if it caused anyone any trouble. I just built guile from head on mac os x 
with this patch applied, an none of the warnings were my fault.

-- 
  Linus Björnstam

0001-Fix-documentation-for-srfi-171.patch
Description: Binary data


define-inlinable* : a define-inlinable with lambda*-behaviour.

2020-04-24 Thread Linus Björnstam
I just found that (ice-9 optargs) has defmacro*, which made me think about a 
question that has popped up on irc about once every 4 months: why isn't there a 
define-inlinable*? 

I have a working implementation, and I want to know if there is any interest to 
include it in guile. Either in boot-9.scm, or as a friend of defmacro* in 
(ice-9 opt-args).

A straight forward simple implementation would have a regression over 
define-inlinable: define-inlinable does arg count validation, which is a lot 
less simple when you have keywords and/or optional arguments. Would this be an 
acceptable regression if they are implemented as two distinct macros?

If one does a proper define-inlinable*, it can be used to implement 
define-inlinable (since that would be the simple case for it).

What do the maintainers think?
-- 
  Linus Björnstam



Re: Guile's time execution issues

2020-04-22 Thread Linus Björnstam
Hi Aleix

Try throwing the result of json->SCM away: (let ((a (call-with...))) 1). Then 
you can run a (gc) between runs. If the GC time increases then, maybe guile 
cannot release the memory?? I don't know, but there is some shared substring 
thing going on in guile, even though I think string-append doesn't do that.

Nice to see that my suggestions worked!
-- 
  Linus Björnstam

On Wed, 22 Apr 2020, at 00:03, Aleix Conchillo Flaqué wrote:
> Hi,
> 
> I was trying to get some guile-json performance times loading large 
> JSON file. However, I'm getting increasing numbers at each run, so I'm 
> wondering if I'm doing something wrong. Below you can see how the first 
> run took 19.95s and then running the same command kept increasing.
> 
> I'm running Guile 2.2.7 on macOS Catalina 10.15.3.
> 
> scheme@(guile-user)> (use-modules (json))
> scheme@(guile-user)> ,t (define a (call-with-input-file 
> "/Users/aleix/Downloads/large-file.json" (lambda (port) (json->scm 
> port
> ;; 19.956429s real time, 87.100982s run time. 75.270202s spent in GC.
> ;; 26.173179s real time, 143.645265s run time. 131.022631s spent in GC.
> ;; 28.193926s real time, 154.758375s run time. 141.697236s spent in GC.
> ;; 29.044218s real time, 160.745984s run time. 147.449073s spent in GC.
> ;; 30.480873s real time, 170.855527s run time. 157.332793s spent in GC.
> ;; 30.555700s real time, 172.938278s run time. 159.468737s spent in GC.
> ;; 32.190478s real time, 172.807551s run time. 158.905645s spent in GC.
> 
> The good news is that I have applied a suggestion from Linus Björnstam 
> that reduces times by half (considering the first run above). The 
> suggestion was to use string ports instead of string-append. And 
> interestingly this time, time executions remain around the same value:
> 
> scheme@(guile-user)> ,t (define a (call-with-input-file 
> "/Users/aleix/Downloads/large-file.json" (lambda (port) (json->scm 
> port
> ;; 9.099597s real time, 17.239176s run time. 9.309819s spent in GC.
> ;; 9.927868s real time, 20.855859s run time. 12.528727s spent in GC.
> ;; 8.981248s real time, 15.043991s run time. 7.050269s spent in GC.
> ;; 9.055893s real time, 15.400981s run time. 7.383187s spent in GC.
> ;; 9.055850s real time, 15.261824s run time. 7.239188s spent in GC.
> ;; 9.315239s real time, 15.231889s run time. 7.005570s spent in GC.
> ;; 9.106168s real time, 14.987678s run time. 6.915028s spent in GC.
> ;; 9.175142s real time, 14.471324s run time. 6.302749s spent in GC.
> ;; 8.966537s real time, 14.400318s run time. 6.412858s spent in GC.
> 
> JSON test data obtained from:
> 
> https://github.com/json-iterator/test-data/blob/master/large-file.json
> 
> Best,
> 
> Aleix



Re: [PATCH] Add srfi-171 to guile

2020-03-23 Thread Linus Björnstam
Hi Ludo! 

All things except some of the docstrings are fixed. The reason not all of the 
docstrings are fixed according to the suggestion is that the reducers you 
specifically used as examples do not return reducers, but ARE reducers, and 
specifically they are srfi-171-styled reducers. i.e: they do not return 
anything, but are meant to be used without calling them: (list-transduce (tmap 
1+) rcons '(1 2 3)), in contrast to (list-transduce (tmap 1+) (revery odd?) '(1 
3 5 6)). All other docstrings and all other suggestions are addressed. 

It compiles fine against the latest master on my ARM64 linux computer.

Best regards
  Linus Björnstam

On Sun, 8 Mar 2020, at 15:40, Ludovic Courtès wrote:
> Hi Linus,
> 
> Linus Björnstam  skribis:
> 
> > From c382d7808a8d41cd4e9ef8a17b7ba9553835499b Mon Sep 17 00:00:00 2001
> > From: =?UTF-8?q?Linus=20Bj=C3=B6rnstam?= 
> > Date: Thu, 16 Jan 2020 20:31:45 +0100
> > Subject: [PATCH] Add SRFI-171 (transducers) to guile.
> >
> > The two guile-specific additions are powerful transducers which can be
> > used to generalize transducers like tsegment. They are hard to get
> > right, but powerful and useful enough to warrant inclusion.
> >
> >  * doc/ref/srfi-modules.texi: added srfi-171 section
> >  * module/Makefile.am (SOURCES):
> >  * module/srfi/srfi-171.scm:
> >  * module/srfi/srfi-171/meta.scm: Add SRFI-171
> >  * module/srfi/srfi-171/gnu.scm: Add 2 guile-specific extensions.
> >  * test-suite/Makefile.am (SCM_TESTS):
> >  * test-suite/tests/srfi-171.test: Add tests.
> 
> I think the patch is almost ready for inclusion, thanks for taking the
> time to address Andy’s comments!
> 
> I have additional stylistic comments, and then I think we’re ready to go:
> 
> > +Transducers are oblivious to what kind of process they are used in, and
> > +are composable without building intermediate collections. This means we
> > +can create a transducer that squares all even numbers: @code{(compose
> > +(tfilter odd?) (tmap (lambda (x) (* x x} and reuse it with lists,
> 
> For readability, it’s probably best to use @example rather than @code
> for the example above (for an example larger than a couple of words in
> general.)
> 
> > +The central part of transducers are 3-arity reducing functions.
> 
> In general, RnRS and Guile use the term “procedure” rather than
> “functions”.  Not a big deal, but bonus points if you can adjust the
> documentation accordingly.  :-)
> 
> > +@itemize
> > +@item
> > +(): Produce an identity
> 
> s/an/the/ ?
> 
> > +@subheading The concept of transducers
> > +
> > +A transducer is a one-arity function that takes a reducer and produces a
> > +reducing function that behaves as follows:
> > +
> > +@itemize
> > +@item
> > +(): calls reducer with no arguments (producing its identity)
> 
> It’s not clear from this where you’d write () (there’s a missing @code
> here, right?), which is not a valid Scheme expression in itself.
> Perhaps an extra bit of introduction is needed above for clarity?
> 
> Also, this is under the “Concept” heading, but it looks more like the
> API, no?
> 
> > +@item
> > +(result-so-far): Maybe transform the result-so-far and call reducer with 
> > it.
> > +
> > +@item
> > +(result-so-far input) Maybe do something to input and maybe call the
> > +reducer with result-so-far and the maybe-transformed input.
> 
> Missing @code ornaments here.
> 
> > +a simple example is as following: @code{ (list-transduce (tfilter odd?)
>   ^
> Capital.
> 
> @example for the example.
> 
> > ++ '(1 2 3 4 5))}. This first returns a transducer filtering all odd
> > +elements, then it runs @code{+} without arguments to retrieve its
> > +identity. It then starts the transduction by passing @code{+} to the
> 
> Please make sure to add two spaces after end-of-sentence periods
> throughout the document.
> 
> > + Even though transducers appear to be somewhat of a generalisation of
> > + map and friends, this is not really true. Since transducers don't know
> 
> s/map/@code{map}/
> 
> > +@deffn {Scheme Procedure} list-transduce xform f lst
> > +@deffnx {Scheme Procedure} list-transduce xform f identity lst
> > + Initializes the transducer @code{xform} by passing the reducer @code{f}
> > + to it. If no identity is provided, @code{f} is run without arguments to
> > + return the reducer identity. It then reduces over @code{lst} using the
> > + identity as the seed.
> 
> Please remove the extra leading space.  Also, use @var, and use
> imperative tense, like so:
> 
>   @deffn {Scheme Proced

Re: [PATCH] Fix of upstream parsing of CDATA

2020-03-12 Thread Linus Björnstam
Oleg replied that he will look into this bug when he has time (and that the 
patch looked reasonable), which sounded non-imminent :) Hopefully this means 
that there will be an upstream patch sometime in the future.

-- 
  Linus Björnstam

On Thu, 16 Jan 2020, at 13:00, Linus Björnstam wrote:
> Hello Guilers!
> 
> RhodiumToad found an error in sxml where it would not properly parse 
> CDATA: > would be converted to > inside CDATA blocks. This is 
> probably due to some wrong reading of the XML spec:
> 
> "Within a CDATA section, only the CDEnd string is recognized as 
> markup, so that left angle brackets and ampersands may occur in their 
> literal form; they need not (and cannot) be escaped using ' < ' and 
> ' & '.".
> 
> Notice that it mentions that only CDEnd is recognized, but omitts > 
> in the enumeration of things that need-not-and-cannot be escaped. 
> 
> No other XML libraries behave this way. Take for example python's Etree:
> 
> Python 2.7.17 (default, Dec 23 2019, 21:25:33)
> >>> import xml.etree.ElementTree as ET
> >>> root = ET.fromstring("")
> >>> root.text
> '>'
> 
> The same thing with the un-patched (sxml ssax) (or rather (sxml 
> simple)): looks different:
> 
> (xml->sxml "")
> ;; => (*TOP* (e ">"))
> 
> The question is whether this patch should be sent upstream. Since there 
> has been very little activity there, I suspect it is a lost cause.
> 
> Failing tests have been looked through, verified and fixed. No 
> unexpected errors were encountered. All SXML tests pass after this 
> patch.
> 
> Best regards
>   Linus Björnstam
> Attachments:
> * 0001-module-sxml-upstream-SSAX.scm-Fix-improper-handling-.patch



Re: guile pipeline do-over

2020-03-10 Thread Linus Björnstam
I have a question about the interface. It uses the shell now, it seems. (I 
could be wrong). The guile system call has a (system cmd ) which uses the shell 
and a system* call which takes (system* cmd arg ...) So that it does not rely 
on the shell. Maybe a similar interface could be useful (and more secure) for 
the pipeline as well.

Thank you for this patch.
  Linus Björnstam

On Tue, 10 Mar 2020, at 08:35, Rutger van Beusekom wrote:
> 
> Hi Ludo,
> 
> I have processed your feedback in this version of the patch.
> 
> Ludovic Courtès writes:
> 
> > Hi Rutger!
> >
> >> ...
> > Nice!  That’s definitely very useful to have.  We’ll need to check what
> > Andy thinks, but I think it can be added in the 3.0 series.
> >
> >
> >> ...
> > Could you mention functions renamed/removed here?  The ChangeLog format
> > is about boringly listing all the language-entity-level changes.  :-)
> >
> Done.
> >
> >> ...
> > I guess you can remove the commented-out bits…
> >
> Yep.
> >
> >> ...
> > … and this hunk, to minimize change.
> >
> Check.
> >
> >> ...
> > I would not export ‘pipe->fdes’.  I’m not sure about exporting
> > ‘piped-process’: it’s a bit low-level and we might want to reserve
> > ourselves the possibility to change it, like this patch does actually.
> >
> > WDYT?
> >
> I agree.
> >> ...
> >
> > Please wrap lines to 80 chars.
> >
> Taken care of.
> >
> >> ...
> >
> > I suggest using ‘string=?’ above instead of ‘equal?’.  Also, could you
> > add a docstring?
> >
> Yes and yes.
> >
> >> ...
> >
> > Perhaps s/procs/commands/ would be clearer?  Also, @var{commands}
> > instead of @code.
> >
> Yep.
> >
> > Could you also add an entry in doc/ref/*.texi, in the “Pipes” node,
> > perhaps with one of the examples you gave?
> >
> Wrote a new example. WDYT?
> >
> >> ...
> >
> > Please move these to the top-level ‘define-module’ form.
> >
> Done.
> >
> > One last thing: we’d need you to assign copyright to the FSF for this.
> > We can discuss it off-line if you want.
> >
> Can you help me there? I already have a verbal commitment from the
> company, we just need to formalize it.
> >
> > Thank you for this great and long overdue addition!
> >
> Happy to add it.
> >
> > Ludo’.
> >
> Rutger
> 
> 
> Attachments:
> * 0001-Add-pipeline-procedure.patch



Re: [PATCH] Add srfi-171 to guile

2020-03-08 Thread Linus Björnstam
Thanks! I will address all those. 

The tests are written and passing, so I will remove the redundant TODOs.

-- 
  Linus Björnstam

On Sun, 8 Mar 2020, at 15:40, Ludovic Courtès wrote:
> Hi Linus,
> 
> Linus Björnstam  skribis:
> 
> > From c382d7808a8d41cd4e9ef8a17b7ba9553835499b Mon Sep 17 00:00:00 2001
> > From: =?UTF-8?q?Linus=20Bj=C3=B6rnstam?= 
> > Date: Thu, 16 Jan 2020 20:31:45 +0100
> > Subject: [PATCH] Add SRFI-171 (transducers) to guile.
> >
> > The two guile-specific additions are powerful transducers which can be
> > used to generalize transducers like tsegment. They are hard to get
> > right, but powerful and useful enough to warrant inclusion.
> >
> >  * doc/ref/srfi-modules.texi: added srfi-171 section
> >  * module/Makefile.am (SOURCES):
> >  * module/srfi/srfi-171.scm:
> >  * module/srfi/srfi-171/meta.scm: Add SRFI-171
> >  * module/srfi/srfi-171/gnu.scm: Add 2 guile-specific extensions.
> >  * test-suite/Makefile.am (SCM_TESTS):
> >  * test-suite/tests/srfi-171.test: Add tests.
> 
> I think the patch is almost ready for inclusion, thanks for taking the
> time to address Andy’s comments!
> 
> I have additional stylistic comments, and then I think we’re ready to go:
> 
> > +Transducers are oblivious to what kind of process they are used in, and
> > +are composable without building intermediate collections. This means we
> > +can create a transducer that squares all even numbers: @code{(compose
> > +(tfilter odd?) (tmap (lambda (x) (* x x} and reuse it with lists,
> 
> For readability, it’s probably best to use @example rather than @code
> for the example above (for an example larger than a couple of words in
> general.)
> 
> > +The central part of transducers are 3-arity reducing functions.
> 
> In general, RnRS and Guile use the term “procedure” rather than
> “functions”.  Not a big deal, but bonus points if you can adjust the
> documentation accordingly.  :-)
> 
> > +@itemize
> > +@item
> > +(): Produce an identity
> 
> s/an/the/ ?
> 
> > +@subheading The concept of transducers
> > +
> > +A transducer is a one-arity function that takes a reducer and produces a
> > +reducing function that behaves as follows:
> > +
> > +@itemize
> > +@item
> > +(): calls reducer with no arguments (producing its identity)
> 
> It’s not clear from this where you’d write () (there’s a missing @code
> here, right?), which is not a valid Scheme expression in itself.
> Perhaps an extra bit of introduction is needed above for clarity?
> 
> Also, this is under the “Concept” heading, but it looks more like the
> API, no?
> 
> > +@item
> > +(result-so-far): Maybe transform the result-so-far and call reducer with 
> > it.
> > +
> > +@item
> > +(result-so-far input) Maybe do something to input and maybe call the
> > +reducer with result-so-far and the maybe-transformed input.
> 
> Missing @code ornaments here.
> 
> > +a simple example is as following: @code{ (list-transduce (tfilter odd?)
>   ^
> Capital.
> 
> @example for the example.
> 
> > ++ '(1 2 3 4 5))}. This first returns a transducer filtering all odd
> > +elements, then it runs @code{+} without arguments to retrieve its
> > +identity. It then starts the transduction by passing @code{+} to the
> 
> Please make sure to add two spaces after end-of-sentence periods
> throughout the document.
> 
> > + Even though transducers appear to be somewhat of a generalisation of
> > + map and friends, this is not really true. Since transducers don't know
> 
> s/map/@code{map}/
> 
> > +@deffn {Scheme Procedure} list-transduce xform f lst
> > +@deffnx {Scheme Procedure} list-transduce xform f identity lst
> > + Initializes the transducer @code{xform} by passing the reducer @code{f}
> > + to it. If no identity is provided, @code{f} is run without arguments to
> > + return the reducer identity. It then reduces over @code{lst} using the
> > + identity as the seed.
> 
> Please remove the extra leading space.  Also, use @var, and use
> imperative tense, like so:
> 
>   @deffn {Scheme Procedure} list-transduce @var{xform} @var{f} @var{lst}
>   Initialize the transducer @var{xform} by passing the reduce @var{f} to
>   it. …
>   @end deffn
> 
> > +If one of the transducers finishes early (such as @code{ttake} or
> > +@code{tdrop}), it communicates this by returning a reduced value, which
> > +in the sample implementation is just a value wrapped in a SRFI 9 record
> > +type named "reduced". If such a value is returned by the transducer,
> 
> For proper typesetting,

Re: Prevent inlining

2020-02-13 Thread Linus Björnstam
Will it not inline "(not-inline x)" and then peval it to x? What are you trying 
to avoid? I am out on very deep water here, now I am just genuinely curious :D
-- 
  Linus Björnstam

On Thu, 13 Feb 2020, at 08:36, Stefan Israelsson Tampe wrote:
> No even if you have cross module inlining you will still be able to 
> tell i a module will allow inlining or not else you will break quite a 
> lot of nice scheme idioms.
> This means that this is indeed future proof.
> 
> On Wed, Feb 12, 2020 at 10:50 PM Linus Björnstam 
>  wrote:
> > If guile ever gets cross-module Inlining in even the simplest form, this 
> > will break. This kind of inlining is probably the most secure one to rely 
> > on ever (my for loops rely on it, for example). A more future proof option 
> > is maybe to (set! ...) A variable within the same module, which makes it 
> > implicitly boxed. Slow unless guile is able to do unboxing...
> > 
> >  Ludo used the trick here: 
> > http://git.savannah.gnu.org/cgit/guile.git/commit/?id=bf1f5422bdb364667d6761dd73454558d6dbf895
> > 
> >  -- 
> >  Linus Björnstam
> > 
> >  On Wed, 12 Feb 2020, at 18:44, Stefan Israelsson Tampe wrote:
> >  > Hi all,
> >  > 
> >  > Current guile inlines even variables exposed in the module interface, 
> >  > and I understand that we must live with that and code around it. So 
> >  > here is a few tips how to mitigate it.
> >  > 
> >  > The simplest way is to put this definition in a module:
> >  > 
> >  > (define-module (syntax not-inline)
> >  > #:export (not-inline))
> >  > 
> >  > (cond-expand
> >  > (guile-3.0
> >  > (define (not-inline x) x))
> >  > ((or (guile-2.0 guile-2.2)
> >  > (define-syntax-rule (not-inline x) x)))
> >  > 
> >  > -
> >  > And then in another module do,
> >  > 
> >  > (use-modules (syntax not-inline))
> >  > (define variable (not-inline 12))
> >  > (define function (not-inline (lambda () ...)))
> >  > etc
> >  > 
> >  > This is also an option (not perfect but you get the gist)
> >  > 
> >  > -
> >  > (define-module (syntax define-not-inlinable)
> >  > #:use-module (syntax not-inline)
> >  > #:export (inline define lambda define* lambda* define-values)
> >  > (define inline (lambda (x) x))
> >  > (define-syntax define
> >  > (syntax-rules (inline)
> >  > ((define (f . x) . code)
> >  > (define f (not-inline (lambda x . code)))
> >  > ((define f (inline x))
> >  > (define f x))
> >  > ((define f x)
> >  > (define f (not-inlinable x
> >  > 
> > --
> >  > using this module will make all usual define not inlineable and to 
> >  > enable inlining you would
> >  > explicitly ask for it like
> >  > 
> >  > (define f (inline (lambda (x) (+ x 10
> >  > 
> >  > If there is a need for this I can write the modules and expose it on 
> >  > the intertubes.
> >  > 
> >  > WDYT
> >  > 
> >  > /Stefan
> >  > 
> >  > 
> >  > 
> >  >



Re: Prevent inlining

2020-02-12 Thread Linus Björnstam
If guile ever gets cross-module Inlining in even the simplest form, this will 
break. This kind of inlining is probably the most secure one to rely on ever 
(my for loops rely on it, for example). A more future proof option is maybe to 
(set! ...) A variable within the same module, which makes it implicitly boxed. 
Slow unless guile is able to do unboxing...

Ludo used the trick here: 
http://git.savannah.gnu.org/cgit/guile.git/commit/?id=bf1f5422bdb364667d6761dd73454558d6dbf895

-- 
  Linus Björnstam

On Wed, 12 Feb 2020, at 18:44, Stefan Israelsson Tampe wrote:
> Hi all,
> 
> Current guile inlines even variables exposed in the module interface, 
> and I understand that we must live with that and code around it. So 
> here is a few tips how to mitigate it.
> 
> The simplest way is to put this definition in a module:
> 
> (define-module (syntax not-inline)
>  #:export (not-inline))
> 
> (cond-expand
>  (guile-3.0
>  (define (not-inline x) x))
>  ((or (guile-2.0 guile-2.2)
>  (define-syntax-rule (not-inline x) x)))
> 
> -
> And then in another module do,
> 
> (use-modules (syntax not-inline))
> (define variable (not-inline 12))
> (define function (not-inline (lambda () ...)))
> etc
> 
> This is also an option (not perfect but you get the gist)
> 
> -
> (define-module (syntax define-not-inlinable)
>  #:use-module (syntax not-inline)
>  #:export (inline define lambda define* lambda* define-values)
> (define inline (lambda (x) x))
> (define-syntax define
>  (syntax-rules (inline)
>  ((define (f . x) . code)
>  (define f (not-inline (lambda x . code)))
>  ((define f (inline x))
>  (define f x))
>  ((define f x)
>  (define f (not-inlinable x
> --
> using this module will make all usual define not inlineable and to 
> enable inlining you would
> explicitly ask for it like
> 
> (define f (inline (lambda (x) (+ x 10
> 
> If there is a need for this I can write the modules and expose it on 
> the intertubes.
> 
> WDYT
> 
> /Stefan
> 
> 
> 
>



Re: unhandled constant?

2020-02-01 Thread Linus Björnstam
tried it in a couple of syntax-case-enabled schemes (defmacro is implemented 
using syntax-case in guile) and it doesn't work anywhere. The procedure ends up 
undefined everywhere.

The # object ,inner points to doesn't exist at runtime because it is 
not defined anywhere in any meaningful way to the compiler. One work-around 
would be to output the literal lambda in place of ,inner but by then you should 
just output a (let ...) With the lambda in it and let the inliner take care of 
it.

-- 
  Linus Björnstam

On Sat, 1 Feb 2020, at 15:23, David Kastrup wrote:
> Linus Björnstam  writes:
> 
> > On Sat, 1 Feb 2020, at 12:09, David Kastrup wrote:
> >> 
> >> Can you expand about the "expansion time and macro time separation"?
> >> 
> >> If we have
> >> 
> >> (define decl '())
> >> (define (make-var n v) (list "var" n v))
> >> (defmacro define-session (name value)
> >>   (define (inner n v)
> >> (set! decl
> >> (cons
> >>  (make-var n v)
> >>  decl))
> >> )
> >>   `(,inner ',name ,value))
> >> (define-session foo 1)
> >> (display decl)
> >> (newline)
> >> 
> >> as stated, the local function "inner" is defined at macro time, but the
> >> form
> >> `(,inner ',name ,value)
> >> does not export the _name_ inner but rather the defined function.  That
> >> part naively appears to me like it should work; an "expansion time and
> >> macro time" issue appears rather to be that inner calls make-var (and
> >> accesses decl) which is only being defined at expansion time.
> >> 
> >> The error message, however, rather appears to complain about inner being
> >> undefined rather than the definition of inner referring to undefined
> >> entities.
> >
> >
> > I am not sure what is really the problem. Either the inner function is
> > not present at runtime due to separation of compile time and runtime,
> > or it is a result of how defmacro re-introduces the result of the
> > macro into the syntactic context of the macro usage (where inner is
> > not visible). Either way, having the inner definition in the macro
> > output will solve the problem of it not being visible.
> 
> This fails when byte-compiling, so it would appear that the equivalent
> of
> 
> (defmacro ...
>   (define local-fun ...
>   `(,local-fun ...)))
> 
> is not able to represent the local (and thus ultimately anonymous)
> function here.  Whether this is a general shortcoming or is conditioned
> on local-fun calling functions not available at byte-compile time (in
> which case those would need to get wrapped in eval-and-expand) I haven't
> checked yet.
> 
> -- 
> David Kastrup
>



Re: unhandled constant?

2020-02-01 Thread Linus Björnstam


On Sat, 1 Feb 2020, at 12:09, David Kastrup wrote:
> 
> Can you expand about the "expansion time and macro time separation"?
> 
> If we have
> 
> (define decl '())
> (define (make-var n v) (list "var" n v))
> (defmacro define-session (name value)
>   (define (inner n v)
> (set! decl
> (cons
>  (make-var n v)
>  decl))
> )
>   `(,inner ',name ,value))
> (define-session foo 1)
> (display decl)
> (newline)
> 
> as stated, the local function "inner" is defined at macro time, but the
> form
> `(,inner ',name ,value)
> does not export the _name_ inner but rather the defined function.  That
> part naively appears to me like it should work; an "expansion time and
> macro time" issue appears rather to be that inner calls make-var (and
> accesses decl) which is only being defined at expansion time.
> 
> The error message, however, rather appears to complain about inner being
> undefined rather than the definition of inner referring to undefined
> entities.


I am not sure what is really the problem. Either the inner function is not 
present at runtime due to separation of compile time and runtime, or it is a 
result of how defmacro re-introduces the result of the macro into the syntactic 
context of the macro usage (where inner is not visible). Either way, having the 
inner definition in the macro output will solve the problem of it not being 
visible.



Re: unhandled constant?

2020-02-01 Thread Linus Björnstam
Did you try just expanding it to a define? Or just output a module-define! at 
runtime and run a module-define! at compile time.



-- 
  Linus Björnstam

On Sat, 1 Feb 2020, at 10:54, Han-Wen Nienhuys wrote:
> Here is an example that shows better how things work, and what might
> be the cause of my problems. Is it right that programmatically set
> contents of "current-module" are not serialized into the compiled
> file?
> 
>(define (run-at-compile-time cmd)
>  (module-define! (current-module) (string->symbol cmd) #t)
>  (format (current-error-port) "I-am-called-at-compile-time ~a\n" cmd))
> 
>   (define (runtime-call cmd)
> (format (current-error-port) "I-am-called-at-runtime ~a\n" cmd)
> (format (current-error-port) "val ~a\n"
> (module-ref (current-module) (string->symbol cmd
> 
>   (defmacro foo (cmd . rest)
>   (run-at-compile-time cmd)
>   `(runtime-call ,cmd))
> 
>   (foo "xy")
> 
> $ guile1.8 ew.scm
> I-am-called-at-compile-time xy
> I-am-called-at-runtime xy
> val #t
> 
> this is compatible with 2.2 without compilation,
> 
> $ GUILE_AUTO_COMPILE=0 guile2.2 ew.scm
> I-am-called-at-compile-time xy
> I-am-called-at-runtime xy
> val #t
> 
> but compilation fails
> 
> $ GUILE_AUTO_COMPILE=1 guile2.2 ew.scm
> ;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
> ;;;   or pass the --no-auto-compile argument to disable.
> ;;; compiling /home/hanwen/vc/lilypond/ew.scm
> ;;; WARNING: compilation of /home/hanwen/vc/lilypond/ew.scm failed:
> ;;; Unbound variable: run-at-compile-time
> 
> $ guild2.2 compile ew.scm
> Backtrace:
> In system/base/target.scm:
>  57:6 19 (with-target _ _)
> In system/base/compile.scm:
> ..
> Unbound variable: run-at-compile-time
> 
> 
> If I encapsulate the run-at-compile-time definition with
> 
>  (eval-when
>   (compile eval)
> 
> it works if I remove the module manipulation, but the module-ref
> doesn't work. It looks like the settings from module-define! are not
> serialized into the byte code, so I can't have code that relies on
> correspondence between module-define driven from macros and module-ref
> during evaluation.
> 
> [hanwen@localhost lilypond]$ guild2.2 compile ew.scm
> I-am-called-at-compile-time xy
> wrote 
> `/home/hanwen/.cache/guile/ccache/2.2-LE-8-3.A/home/hanwen/vc/lilypond/ew.scm.go'
> [hanwen@localhost lilypond]$ GUILE_AUTO_COMPILE=0 guile2.2 ew.scm
> I-am-called-at-runtime xy
> Backtrace:
>6 (apply-smob/1 #)
> In ice-9/boot-9.scm:
> 705:2  5 (call-with-prompt ("prompt") # …)
> In ice-9/eval.scm:
> 619:8  4 (_ #(#(#)))
> In ice-9/boot-9.scm:
>    2312:4  3 (save-module-excursion #)
>   3832:12  2 (_)
> In ew.scm:
> 10:10  1 (runtime-call "xy")
> In unknown file:
>0 (scm-error misc-error #f "~A ~S ~S ~S" ("No variabl…" …) …)
> 
> ERROR: In procedure scm-error:
> No variable named xy in #
> 
> On Fri, Jan 31, 2020 at 9:01 PM Linus Björnstam
>  wrote:
> >
> > Read the docs. That seems to be a documentation bug. Try fiddling with the 
> > arguments to eval when and see if you can make it work.
> >
> > --
> >   Linus Björnstam
> >
> > On Fri, 31 Jan 2020, at 20:17, Han-Wen Nienhuys wrote:
> > > On Fri, Jan 31, 2020 at 7:20 PM Linus Björnstam
> > >  wrote:
> > > > I don't really understand your question. With defmacro and syntax-case 
> > > > you can run arbitrary code. If you just output code that does 
> > > > module-define! that won't be run until runtime, and thus you cannot 
> > > > depend on the result of that module-define! during expansion. You can 
> > > > however wrap it in an eval-when to solve that issue. That allows you to 
> > > > specify when code gets run. With module-define! I personally find it 
> > > > all a bit icky, but I usually stay as far away from phasing as I can :)
> > >
> > >  eval-when looks like it might be a solution to the puzzle , but
> > > honestly, the doc at
> > >
> > > https://www.gnu.org/software/guile/manual/html_node/Eval-When.html
> > >
> > > has me mystified.  When I run the example through guile 2.2 and
> > > display *compilation-date*,
> > >
> > > I get a different answer each time. Shouldn't it be a fixed timestamp
> > > (of when the compile happened?)
> > >
> > > [hanwen@localhost lilypond]$ guile2.2 e.scm
> > > ;;; note: source file /home/hanwen/vc/lilypond/e.scm
> 

Re: unhandled constant?

2020-01-31 Thread Linus Björnstam
Read the docs. That seems to be a documentation bug. Try fiddling with the 
arguments to eval when and see if you can make it work.

-- 
  Linus Björnstam

On Fri, 31 Jan 2020, at 20:17, Han-Wen Nienhuys wrote:
> On Fri, Jan 31, 2020 at 7:20 PM Linus Björnstam
>  wrote:
> > I don't really understand your question. With defmacro and syntax-case you 
> > can run arbitrary code. If you just output code that does module-define! 
> > that won't be run until runtime, and thus you cannot depend on the result 
> > of that module-define! during expansion. You can however wrap it in an 
> > eval-when to solve that issue. That allows you to specify when code gets 
> > run. With module-define! I personally find it all a bit icky, but I usually 
> > stay as far away from phasing as I can :)
> 
>  eval-when looks like it might be a solution to the puzzle , but
> honestly, the doc at
> 
> https://www.gnu.org/software/guile/manual/html_node/Eval-When.html
> 
> has me mystified.  When I run the example through guile 2.2 and
> display *compilation-date*,
> 
> I get a different answer each time. Shouldn't it be a fixed timestamp
> (of when the compile happened?)
> 
> [hanwen@localhost lilypond]$ guile2.2 e.scm
> ;;; note: source file /home/hanwen/vc/lilypond/e.scm
> ;;;   newer than compiled
> /home/hanwen/.cache/guile/ccache/2.2-LE-8-3.A/home/hanwen/vc/lilypond/e.scm.go
> ;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
> ;;;   or pass the --no-auto-compile argument to disable.
> ;;; compiling /home/hanwen/vc/lilypond/e.scm
> ;;; compiled 
> /home/hanwen/.cache/guile/ccache/2.2-LE-8-3.A/home/hanwen/vc/lilypond/e.scm.go
> Fri Jan 31 20:15:57+0100 2020
> [hanwen@localhost lilypond]$ guile2.2 e.scm
> Fri Jan 31 20:15:58+0100 2020
> [hanwen@localhost lilypond]$ guile2.2 e.scm
> Fri Jan 31 20:16:00+0100 2020
> 
> -- 
> Han-Wen Nienhuys - hanw...@gmail.com - http://www.xs4all.nl/~hanwen
>



Re: unhandled constant?

2020-01-31 Thread Linus Björnstam


On Fri, 31 Jan 2020, at 20:17, Han-Wen Nienhuys wrote:
> 
>  eval-when looks like it might be a solution to the puzzle , but
> honestly, the doc at
> 
> https://www.gnu.org/software/guile/manual/html_node/Eval-When.html
> 
> has me mystified.  When I run the example through guile 2.2 and
> display *compilation-date*,
> 
> I get a different answer each time. Shouldn't it be a fixed timestamp
> (of when the compile happened?)

Yup. At least from my understanding of the documentation, but whenever I try to 
do eval-when I become sad so I have just decided that I am too dumb for it. Try 
asking in the irc channel.




Re: unhandled constant?

2020-01-31 Thread Linus Björnstam
I'm not very familiar with how guile 1.8 works since my first guile version was 
2.2, but I remember hearing Andy talk about how macro expansion was done at 
runtime, due to guile not being compiled.

I just put one and one together and figured that the reason the macro you 
posted works in 1.8 must be because of what basically rounds down to no 
separation between runtime and expand time.

Defmacro is expanded to a regular syntax case macro that first strips all 
syntax information and passes it to the defmacro body and the re-introduces the 
result. Regarding your other question: any literal string in the defmacro body 
is moved to the correct define-syntax placement.

I don't really understand your question. With defmacro and syntax-case you can 
run arbitrary code. If you just output code that does module-define! that won't 
be run until runtime, and thus you cannot depend on the result of that 
module-define! during expansion. You can however wrap it in an eval-when to 
solve that issue. That allows you to specify when code gets run. With 
module-define! I personally find it all a bit icky, but I usually stay as far 
away from phasing as I can :)



-- 
  Linus Björnstam

On Fri, 31 Jan 2020, at 18:50, Han-Wen Nienhuys wrote:
> On Fri, Jan 31, 2020 at 3:58 PM Linus Björnstam
>  wrote:
> >
> > Guile1.8's macros are run-time macros: they are executed directly and not 
> > transformed to output code that is then compiled. That is the reason why 
> > your code works: to newer guiles the (inner ...) is only available at 
> > expansion time. The macro output is trying to call code that does not exist 
> > at runtime!
> 
> When is the code executed?  If have complex set of macros to define a
> special type of functions (so called markup commands).  Some of these
> refer to other markup commands through a macro.
> 
> What I can observe that some of the functions involved are not called
> during the compilation, but others are.
> 
> In particular, the function that registers a markup command using something 
> like
> 
>   (module-define! (current-module)
>   (string->symbol (format #f "~a-markup" name))   defn))
> 
> but this function is not called during the compile
> 
> There is a convenience macro that is called within some function
> bodies, that does get called. Unfortunately, the latter convenience
> macro is expanded and then executed; the execution tries to then do
> 
>(module-ref (current-module)
>   (string->symbol (format #f "~a-markup" name)
> 
> which fails.
> 
> 
> 
> > For this to be working code the (inner ...) function needs to be available 
> > in the macro expansion. I didn't read through exactly what you are trying 
> > to do, but try outputting a let:
> >
> > `(let ((inner (lambda (n v) (set ! ...))))
> >   (inner ,name ,value))
> >
> > I doubt you can make the old code work in newer guiles, since I doubt any 
> > scheme is a s lax about expansion time and macro time separation.
> > --
> >   Linus Björnstam
> >
> > On Wed, 29 Jan 2020, at 00:08, Han-Wen Nienhuys wrote:
> > > Some of the lilypond Scheme files do the following:
> > >
> > >
> > > (define decl '())
> > > (define (make-var n v) (list "var" n v))
> > > (defmacro define-session (name value)
> > >   (define (inner n v)
> > > (set! decl
> > > (cons
> > >  (make-var n v)
> > >  decl))
> > > )
> > >   `(,inner ',name ,value))
> > > (define-session foo 1)
> > > (display decl)
> > > (newline)
> > >
> > > In GUILE 2.2, this yields
> > >
> > > ;;; WARNING: compilation of /home/hanwen/vc/lilypond/q.scm failed:
> > > ;;; unhandled constant #
> > >
> > > What does this error message mean, and what should I do to address the 
> > > problem?
> > > --
> > > Han-Wen Nienhuys - hanw...@gmail.com - http://www.xs4all.nl/~hanwen
> > >
> > >
> 
> 
> 
> -- 
> Han-Wen Nienhuys - hanw...@gmail.com - http://www.xs4all.nl/~hanwen
>



Re: unhandled constant?

2020-01-31 Thread Linus Björnstam
Guile1.8's macros are run-time macros: they are executed directly and not 
transformed to output code that is then compiled. That is the reason why your 
code works: to newer guiles the (inner ...) is only available at expansion 
time. The macro output is trying to call code that does not exist at runtime!

For this to be working code the (inner ...) function needs to be available in 
the macro expansion. I didn't read through exactly what you are trying to do, 
but try outputting a let:

`(let ((inner (lambda (n v) (set ! ...
  (inner ,name ,value))

I doubt you can make the old code work in newer guiles, since I doubt any 
scheme is a s lax about expansion time and macro time separation.
-- 
  Linus Björnstam

On Wed, 29 Jan 2020, at 00:08, Han-Wen Nienhuys wrote:
> Some of the lilypond Scheme files do the following:
> 
> 
> (define decl '())
> (define (make-var n v) (list "var" n v))
> (defmacro define-session (name value)
>   (define (inner n v)
> (set! decl
> (cons
>  (make-var n v)
>  decl))
> )
>   `(,inner ',name ,value))
> (define-session foo 1)
> (display decl)
> (newline)
> 
> In GUILE 2.2, this yields
> 
> ;;; WARNING: compilation of /home/hanwen/vc/lilypond/q.scm failed:
> ;;; unhandled constant #
> 
> What does this error message mean, and what should I do to address the 
> problem?
> -- 
> Han-Wen Nienhuys - hanw...@gmail.com - http://www.xs4all.nl/~hanwen
> 
>



Re: Fwd: Announcing the first stable release of guile-for-loops

2020-01-24 Thread Linus Björnstam
Yeah, when iterating through many different things at the same time it is 
extremely helpful. 

I would have loved syntax parse when writing the macros :) I read your for 
loops code in awe, at least until I saw how you "cheated" with set! :-P

My only chance of getting it into guile proper would be to 1. Make a SRFI and 
survive the SRFI process with my honour intact and 2. Code cleanup. Most of 
for/emit is OKish, but for/foldr needs to be beaten with a stick, burnt and 
rewritten. "bending hygiene" doesn't quite cover what I did to make it work. In 
the end I sort of kind of worked around it by making an API change, but it 
still stinks. Defining a new loop using for/foldr involves having to do a 
syntax->datum->syntax. No fun. I could check how racket does it, but given they 
can do syntax-local-introduce (which is specific to their "hygiene as sets of 
scopes") I suspect I am out of luck. 

Väl mött
  Linus Björnstam

On Fri, 24 Jan 2020, at 13:13, Stefan Israelsson Tampe wrote:
> 
> 
> -- Forwarded message -
> From: *Stefan Israelsson Tampe* 
> Date: Fri, Jan 24, 2020 at 12:42 PM
> Subject: Re: Announcing the first stable release of guile-for-loops
> To: Linus Björnstam 
> 
> 
> Would be cool to have those implemented in guile, that would make my 
> guile-syntax-parse a bit leaner
> 
> Regards
> Stefan
> 
> On Thu, Jan 23, 2020 at 3:03 PM Linus Björnstam 
>  wrote:
> > Hiya everybody!
> > 
> >  I have spent some time implementing efficient for loops for guile, and 
> > they are baked and ready to go. I have worked the last weeks at 
> > implementing generalized support for non-tail-recursive loops and am happy 
> > to announce for/foldr. It is a generic right fold, with support for 
> > delaying it's arguments as either thunks or promises. 
> > 
> >  The syntax is more or less the same as racket's loops, and they are 
> > generally compatible. The code generated is for almost all cases as fast as 
> > hand-rolled code. They are all expressed as left or right folds, and are as 
> > such (apart from for/list, but read about that in the documentation) free 
> > of mutation. They are all converted to named lets. 
> > 
> >  Some examples:
> > 
> >  (for/list ((a (in-range 1 6)))
> >  (* a a)) ;; => (1 4 9 16 25)
> > 
> >  (for*/list ((a (in-string "ab")) (b (in-range 1 3)))
> >  (list a b)) 
> >  ;; => ((#\a 1) (#\a 2) (#\b 1) (#\b 2))
> > 
> >  There are many more looping constructs, among others: 
> >  for/sum, for/vector, for/or, for/and, for/first, for/last and a 
> > side-effecting simple for.
> > 
> >  Here is a sieve of erathostenes:
> > 
> >  (define (erathostenes n)
> >  (define vec (make-vector n #t))
> >  (for/list ([i (in-range 2 n)] #:when (vector-ref vec i))
> >  (for ([j (in-range/incr (* 2 i) n i)])
> >  (vector-set! vec j #f))
> >  i))
> > 
> >  The code and documentation is available here: 
> > https://hg.sr.ht/~bjoli/guile-for-loops
> > 
> >  A web-friendly documentation can be found here: 
> > https://man.sr.ht/%7Ebjoli/for-loops-docs/for-loops.md 
> > <https://man.sr.ht/~bjoli/for-loops-docs/for-loops.md>
> > 
> >  The thing I had been waiting for is right fold. That allows us to write 
> > loops like guile's map: non-tail recursive:
> >  (for/foldr ((identity '())) ((a (in-list '(1 2 3
> >  (cons (* a a) identity))
> > 
> >  becomes equivalent to:
> > 
> >  (let loop ((random-identifier '(1 2 3)))
> >  (if (null? random-identifier)
> >  '()
> >  (let ((a (car random-identifier)))
> >  (cons (* a a) (loop (cdr random-identifier))
> > 
> >  Happy hacking
> >  Linus Björnstam
> >



Announcing the first stable release of guile-for-loops

2020-01-23 Thread Linus Björnstam
Hiya everybody!

I have spent some time implementing efficient for loops for guile, and they are 
baked and ready to go. I have worked the last weeks at implementing generalized 
support for non-tail-recursive loops and am happy to announce for/foldr. It is 
a generic right fold, with support for delaying it's arguments as either thunks 
or promises. 

The syntax is more or less the same as racket's loops, and they are generally 
compatible. The code generated is for almost all cases as fast as hand-rolled 
code. They are all expressed as left or right folds, and are as such (apart 
from for/list, but read about that in the documentation) free of mutation. They 
are all converted to named lets. 

Some examples:

(for/list ((a (in-range 1 6)))
  (* a a)) ;; => (1 4 9 16 25)

(for*/list ((a (in-string "ab")) (b (in-range 1 3)))
  (list a b)) 
;; => ((#\a 1) (#\a 2) (#\b 1) (#\b 2))

There are many more looping constructs, among others: 
for/sum, for/vector, for/or, for/and, for/first, for/last and a side-effecting 
simple for.

Here is a sieve of erathostenes:

(define (erathostenes n)
  (define vec (make-vector n #t))
  (for/list ([i (in-range 2 n)] #:when (vector-ref vec i))
(for ([j (in-range/incr (* 2 i) n i)])
  (vector-set! vec j #f))
i))

The code and documentation is available here: 
https://hg.sr.ht/~bjoli/guile-for-loops

A web-friendly documentation can be found here: 
https://man.sr.ht/%7Ebjoli/for-loops-docs/for-loops.md

The thing I had been waiting for is right fold. That allows us to write loops 
like guile's map: non-tail recursive:
(for/foldr ((identity '())) ((a (in-list '(1 2 3
  (cons (* a a) identity))

becomes equivalent to:

(let loop ((random-identifier '(1 2 3)))
  (if (null? random-identifier)
  '()
  (let ((a (car random-identifier)))
(cons (* a a) (loop (cdr random-identifier))

Happy hacking
Linus Björnstam



Re: GNU Guile 3.0.0 released

2020-01-19 Thread Linus Björnstam

On 2020-01-16 22:35, Arne Babenhauserheide wrote:


Can we get this into the Scheme standard, too?


If you want a portable implementation, you can actually hack it using 
macros. Re-define lambda, define, let(*,-values,letrec,letrec*) and 
begin to rewrite everything to letrec and you are done! The problem is 
that it will be slower than using let* for the bindings that don't 
require letrec in many schemes, since the don't do the equivilent of 
guile's letrectification pass (described in the paper "Letrec done right 
(reloaded)" iirc).



I have a syntax-rules implementation of it if you are interested, that 
also supports a simplified define-like binding that converts to let*. 
That one does _not_ convert the body to one letrec, only defines 
following eachother.


so

(define a 1)

(when (even? a) (error "ERROR"))

(define b 2)

becomes

(letrec ((a ...))
  (when (even? a) (error "ERROR"))
(letrec ((b 2))
  ...)

This is not compatible with guile, but is trivial to fix!

Trivially portable to any other scheme, since it uses no fancy features 
except the usual module things:


https://hg.sr.ht/~bjoli/guile-define/




Re: GNU Guile 3.0.0 released

2020-01-19 Thread Linus Björnstam
If you want a portable implementation, you can actually hack it using 
macros. Re-define lambda, define, let(*,-values,letrec,letrec*),cond, 
case and begin to rewrite everything to letrec and you are done! The 
problem is that it will be slower than using let* for the bindings that 
don't require letrec in many schemes, since the don't do the equivilent 
of guile's letrectification pass (described in the paper "Letrec done 
right (reloaded)" iirc).


I have a syntax-rules implementation of it if you are interested, that 
also supports a simplified define-like binding that converts to let*. 
That one does _not_ convert the body to one letrec, only defines 
following eachother.


so

(define a 1)

(when (even? a) (error "ERROR"))

(define b 2)

becomes

(letrec ((a ...))
  (when (even? a) (error "ERROR"))
    (letrec ((b 2))
  ...)

This is not compatible with guile, but is trivial to fix!

Trivially portable to any other scheme, since it uses no fancy features 
except the usual module things:


https://hg.sr.ht/~bjoli/guile-define/

On 2020-01-16 22:35, Arne Babenhauserheide wrote:

Andy Wingo  writes:


We are delighted to announce GNU Guile release 3.0.0, the first in the
new 3.0 stable release series.

…

The Guile web page is located at http://gnu.org/software/guile/

That’s awesome! Thank you for your work!


Changes in 3.0.0 (since the stable 2.2 series):

…

** Just-in-time code generation

Guile programs now run up to 4 times faster, relative to Guile 2.2,
thanks to just-in-time (JIT) native code generation.  Notably, this
brings the performance of "eval" as written in Scheme back to the level
of "eval" written in C, as in the days of Guile 1.8.

This is awesome! I hope it finally alleviates the problems faced by Lilypond!


** Interleaved internal definitions and expressions allowed

I love that! It removes one of the early stumbling points I had with
Guile which pushed me to avoid inner defines. I only realized later how
much more readable code gets with inner defines.

Can we get this into the Scheme standard, too?


** `guard' no longer unwinds the stack for clause tests

SRFI-34, and then R6RS and R7RS, defines a `guard' form that is a
shorthand for `with-exception-handler'.  The cond-like clauses for the
exception handling are specified to run with the continuation of the
`guard', while any re-propagation of the exception happens with the
continuation of the original `raise'.

…

Guile now works around these issues by running the test portion of the
guard expressions within the original `raise' continuation, and only
unwinding once a test matches.  This is an incompatible semantic change
but we think the situation is globally much better, and we expect that
very few people will be affected by the change.

Is this semantic change a change from previous Guile or a deviation from
the Scheme standard?

Best wishes,
Arne
--
Unpolitisch sein
heißt politisch sein
ohne es zu merken


--
 - Linus Björnstam




Re: debug enable seems broken in 3.0

2020-01-18 Thread Linus Björnstam


There is no 'debug options, as the error says. Read more here: 
https://www.gnu.org/software/guile/manual/html_node/Debug-Options.html#index-debug_002denable
-- 
  Linus Björnstam

On Sat, 18 Jan 2020, at 19:45, dsm...@roadrunner.com wrote:
> This ought to work, right?
> 
> From a fresh 3.0 install from tarball on Debian Buster:
> 
> $ guile
> 
> GNU Guile 3.0.0
> 
> Copyright (C) 1995-2020 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)> (debug-enable 'debug)
> 
> ice-9/boot-9.scm:1669:16: In procedure raise-exception:
> 
> In procedure debug-options-interface: Unknown option name: debug
> 
> 
> 
> Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.
> 
> scheme@(guile-user) [1]> ,bt
> 
> In ice-9/boot-9.scm:
> 
>  3609:0 2 (debug-enable . _)
> 
> In unknown file:
> 
>  1 (debug-options-interface (debug show-file-name #t # # …))
> 
> In ice-9/boot-9.scm:
> 
>  1669:16 0 (raise-exception _ #:continuable? _)
> 
> scheme@(guile-user) [1]> 
> 
> 
>



Re: Logo baseline

2020-01-18 Thread Linus Björnstam
Fun I can agree with! It is what made me stick with Guile in the first place.

GNU as an adjective seems odd: I think that can better be conveyed as a part of 
the name "GNU Guile". It is and, if I have understood the discussions going on 
here, will continue to be a GNU project. Maybe treat fun as a noun: GNU Guile - 
fast functional fun :D

I'd leave the fine details of taglines to someone who is better versed in 
english than me, though.
-- 
  Linus Björnstam

On Sat, 18 Jan 2020, at 15:08, Ludovic Courtès wrote:
> Hello Guilers!
> 
> The Guile logo has this “GNU extension language” baseline.  As Guile 3
> came out, this baseline felt odd to me, not quite corresponding to the
> way I see Guile.
> 
> Clearly, Guile is still an extension language, with many great
> applications (Gnucash, Lepton-EDA, OpenCog, GDB, etc.), and I’m sure
> libguile is here to stay.  Yet, to me, “extension language” does not
> accurately capture what Guile today allows for and what people have been
> doing with it; since 2.0, it’s more than an extension language, even
> more so with the performance afforded by Guile 3.
> 
> Thus, I’d propose changing the baseline.  Something that would describe
> what Guile is to me is:
> 
>   GNU, fast, fun, functional
> 
> What’s about you?  What’s Guile to you?  :-)
> 
> Ludo’.
> 
> Attachments:
> * signature.asc



Re: [PATCH] Add srfi-171 to guile

2020-01-16 Thread Linus Björnstam
I have addressed all your feedback and present to you the revised patch. 
Some small code changes compared to the other patch. Most significantly, 
tsegment and tpartition have gotten paranoid about the downstream 
reducer managing to sneak a reduced value through (with no performance 
impact, mind you). Apart from that, some docstrings were added where it 
seemed sane, some accidental code duplication between (srfi srfi-171) 
and (srfi srfi-171 meta) was fixed.


The only thing I am scared of is thunderbird accidentally sending this 
mail as HTML and maybe getting the commit message formatting wrong.


Best regards

Linus Björnstam



On 2020-01-05 12:30, Andy Wingo wrote:

Hi :)

Since this is a final SRFI I think there's no problem getting it in.
Some formatting notes follow; since it's your first Guile patch I'm a
bit verbose :)  Probably this will miss 3.0.0 but make 3.0.1, FWIW.

On Sun 22 Dec 2019 15:55, Linus Björnstam  writes:


 From 7e8d3b22ba5f814c40dbb5ab616a318c0cdc2f3e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Linus=20Bj=C3=B6rnstam?= 
Date: Sun, 22 Dec 2019 15:38:34 +0100
Subject: [PATCH 1/2] Added srfi-171 to guile under the module name (srfi
  srfi-171).

For more info, read the SRFI document: 
https://srfi.schemers.org/srfi-171/srfi-171.html

Needs a note per-file; see other commit log messages.  Also please wrap
to 72 characters.


--- /dev/null
+++ b/module/srfi/srfi-171.scm
@@ -0,0 +1,498 @@
+;
+;; Copyright 2019 Linus Bj.rnstam
+;;

I think you've assigned copyright so this can have the standard Guile
copyright block, right?


+;; This module name is guile-specific. The correct module name is of course
+;; (srfi 171)

I don't think it's right to say there is a "correct" name.  R6RS, R7RS,
and Guile have different naming conventions for SRFI modules and that's
OK.

The style in Guile is generally that block comments like this should be
complete sentences, starting with capital letters and including
terminating punctuation.  Generally we do two spaces after periods,
also.


+(define-module (srfi srfi-171)
+  #:declarative? #t
+  #:use-module (srfi srfi-9)
+  #:use-module ((srfi srfi-43)
+#:select (vector->list))
+  #:use-module ((srfi srfi-69) #:prefix srfi69:)
+  #:use-module ((rnrs hashtables) #:prefix rnrs:)
+  #:use-module (srfi srfi-171 meta)
+  #:export (rcons reverse-rcons
+  rcount
+  rany

Better to put rcons on its own line so that other exports are also
aligned with the open paren.


+;; A special value to be used as a placeholder where no value has been set and 
#f
+;; doesn't cut it. Not exported.
+
+(define-record-type 
+  (make-nothing)
+  nothing?)
+(define nothing (make-nothing))

Note that this can be somewhat cheaper as:

   (define nothing (list 'nothing))
   (define (nothing? x) (eq? x nothing))


+;; helper function which ensures x is reduced.

Capitalize.  FWIW, better done as a docstring:

   (define (ensure-reduced x)
 "Ensure that @var{x} is reduced."
 ...)


+;; helper function that wraps a reduced value twice since reducing functions 
(like list-reduce)
+;; unwraps them. tconcatenate is a good example: it re-uses it's reducer on 
it's input using list-reduce.
+;; If that reduction finishes early and returns a reduced value, list-reduce would 
"unreduce"
+;; that value and try to continue the transducing process.

Capitalize and limit to 80 characters wide.


+(define (preserving-reduced f)
+  (lambda (a b)
+(let ((return (f a b)))
+  (if (reduced? return)
+  (reduced return)
+  return
+
+
+
+

Generally, put one blank line between functions.  Two lines can be
between sections.  Four is too much :)


+
+;; Reducing functions meant to be used at the end at the transducing
+;; process.;

This is a fairly non-standard comment style, FWIW; consider just
prefixing with "".


+;; a transducer-friendly cons with the empty list as identity
+(define rcons
+  (case-lambda

Similar comment regarding docstrings


+;; Use this as the f in transduce to count the amount of elements passed 
through.
+;; (transduce (tfilter odd?) tcount (list 1 2 3)) => 2

80 characters, and the example can go in an @example if you like:

   (define rcount
 (case-lambda
   "A transducer that counts the number of elements passing through. \
@example
(transduce (tfilter odd?) tcount (list 1 2 3)) @result{} 2
@end example"
   ...))


+(define (make-replacer map)
+  (cond
+   ((list? map)
+(lambda (x)
+  (let ((replacer? (assoc x map)))
+(if replacer?
+(cdr replacer?)
+x

I generally find this sort of thing better with (ice-9 match):

   (match (a

[PATCH] Fix of upstream parsing of CDATA

2020-01-16 Thread Linus Björnstam
Hello Guilers!

RhodiumToad found an error in sxml where it would not properly parse CDATA: > 
would be converted to > inside CDATA blocks. This is probably due to some wrong 
reading of the XML spec:

"Within a CDATA section, only the CDEnd string is recognized as markup, so 
that left angle brackets and ampersands may occur in their literal form; they 
need not (and cannot) be escaped using ' < ' and ' & '.".

Notice that it mentions that only CDEnd is recognized, but omitts > in the 
enumeration of things that need-not-and-cannot be escaped. 

No other XML libraries behave this way. Take for example python's Etree:

Python 2.7.17 (default, Dec 23 2019, 21:25:33)
>>> import xml.etree.ElementTree as ET
>>> root = ET.fromstring("")
>>> root.text
'>'

The same thing with the un-patched (sxml ssax) (or rather (sxml simple)): looks 
different:

(xml->sxml "")
;; => (*TOP* (e ">"))

The question is whether this patch should be sent upstream. Since there has 
been very little activity there, I suspect it is a lost cause.

Failing tests have been looked through, verified and fixed. No unexpected 
errors were encountered. All SXML tests pass after this patch.

Best regards
  Linus Björnstam

0001-module-sxml-upstream-SSAX.scm-Fix-improper-handling-.patch
Description: Binary data


Re: [PATCH] Add string-replace-substring to (ice-9 string-fun)

2020-01-06 Thread Linus Björnstam
Did you try it with a "better" string-contains? IIRC the guile one is a naive 
string search (but in C) which could maybe be better if it was implemented as, 
say, a KMP search. The reference srfi-13 has one you could try. That could be 
faster for longer strings and longer patterns. 

If that is faster, I can port a constant-space one that I have in ocaml 
somewhere in the catacombs of my.computer.

-- 
  Linus Björnstam

On Fri, 20 Dec 2019, at 18:32, lloda wrote:
> 
> This patch adds string-replace-substring that wingo posted to the 
> mailing list to (ice-9 strings). This is a commonly used function and a 
> good implementation isn't trivial, so I think it deserves inclusion.
> 
> 
> 
> Attachments:
> * 0001-Add-string-replace-substring-to-ice-9-string-fun.patch



Re: [PATCH] Add srfi-171 to guile

2020-01-05 Thread Linus Björnstam
Thanks for taking time to review it!

I will make a new patch with all your proposed changes.

Don't mind the correctness comments, btw. They are a rest from the first 
successful implementation when I had a less clear mental model of how 
transducers worked. I know how to verify and test that they work as they 
should. 

Regarding the copyright block I was a bit too trigger happy. I completely 
forgot!

I have loads at work right now (2 weeks of modern music cd recording. Fun 
times!), but so will make sure to try to get everything done before the end of 
January.

Best regards
  Linus Björnstam

On Sun, 5 Jan 2020, at 12:30, Andy Wingo wrote:
> Hi :)
> 
> Since this is a final SRFI I think there's no problem getting it in.
> Some formatting notes follow; since it's your first Guile patch I'm a
> bit verbose :)  Probably this will miss 3.0.0 but make 3.0.1, FWIW.
> 
> On Sun 22 Dec 2019 15:55, Linus Björnstam  
> writes:
> 
> > From 7e8d3b22ba5f814c40dbb5ab616a318c0cdc2f3e Mon Sep 17 00:00:00 2001
> > From: =?UTF-8?q?Linus=20Bj=C3=B6rnstam?= 
> > Date: Sun, 22 Dec 2019 15:38:34 +0100
> > Subject: [PATCH 1/2] Added srfi-171 to guile under the module name (srfi
> >  srfi-171).
> >
> > For more info, read the SRFI document: 
> > https://srfi.schemers.org/srfi-171/srfi-171.html
> 
> Needs a note per-file; see other commit log messages.  Also please wrap
> to 72 characters.
> 
> > --- /dev/null
> > +++ b/module/srfi/srfi-171.scm
> > @@ -0,0 +1,498 @@
> > +;
> > +;; Copyright 2019 Linus Bj.rnstam
> > +;;
> 
> I think you've assigned copyright so this can have the standard Guile
> copyright block, right?
> 
> > +;; This module name is guile-specific. The correct module name is of course
> > +;; (srfi 171)
> 
> I don't think it's right to say there is a "correct" name.  R6RS, R7RS,
> and Guile have different naming conventions for SRFI modules and that's
> OK.
> 
> The style in Guile is generally that block comments like this should be
> complete sentences, starting with capital letters and including
> terminating punctuation.  Generally we do two spaces after periods,
> also.
> 
> > +(define-module (srfi srfi-171)
> > +  #:declarative? #t
> > +  #:use-module (srfi srfi-9)
> > +  #:use-module ((srfi srfi-43)
> > +#:select (vector->list))
> > +  #:use-module ((srfi srfi-69) #:prefix srfi69:)
> > +  #:use-module ((rnrs hashtables) #:prefix rnrs:)
> > +  #:use-module (srfi srfi-171 meta)
> > +  #:export (rcons reverse-rcons
> > +  rcount
> > +  rany
> 
> Better to put rcons on its own line so that other exports are also
> aligned with the open paren.
> 
> > +;; A special value to be used as a placeholder where no value has been set 
> > and #f
> > +;; doesn't cut it. Not exported.
> > +
> > +(define-record-type 
> > +  (make-nothing)
> > +  nothing?)
> > +(define nothing (make-nothing))
> 
> Note that this can be somewhat cheaper as:
> 
>   (define nothing (list 'nothing))
>   (define (nothing? x) (eq? x nothing))
> 
> > +;; helper function which ensures x is reduced.
> 
> Capitalize.  FWIW, better done as a docstring:
> 
>   (define (ensure-reduced x)
> "Ensure that @var{x} is reduced."
> ...)
> 
> > +;; helper function that wraps a reduced value twice since reducing 
> > functions (like list-reduce)
> > +;; unwraps them. tconcatenate is a good example: it re-uses it's reducer 
> > on it's input using list-reduce.
> > +;; If that reduction finishes early and returns a reduced value, 
> > list-reduce would "unreduce"
> > +;; that value and try to continue the transducing process.
> 
> Capitalize and limit to 80 characters wide.
> 
> > +(define (preserving-reduced f)
> > +  (lambda (a b)
> > +(let ((return (f a b)))
> > +  (if (reduced? return)
> > +  (reduced return)
> > +  return
> > +
> > +
> > +
> > +
> 
> Generally, put one blank line between functions.  Two lines can be
> between sections.  Four is too much :)
> 
> > +
> > +;; Reducing functions meant to be used at the end at the transducing
> > +;; process.;
> 
> This is a fairly non-standard comment style, FWIW; consider just
> prefixing with "".
> 
> > +;; a transdu

Re: [PATCH] Add srfi-171 to guile

2019-12-22 Thread Linus Björnstam
I forgot the copyright!

All the papers are in order with the FSF for the copyright assignment.

-- 
  Linus Björnstam

On Sun, 22 Dec 2019, at 15:55, Linus Björnstam wrote:
> Hi there!
> 
> This is a patch to add srfi-171 (transducers) to guile. 
> 
> It adds the srfi implementation, a guile-specific extension (tfold and 
> tbatch which can be used to generalize things like tsegment), 
> documentation (the whole srfi document plus additions into 
> srfi-modules.texi) and tests. 
> 
> I have built it successfully on the latest master. This would be my 
> first ever commit to a project I did not start myself, with the added 
> bonus that I have no idea of how git works. Be kind :)
> 
> Happy holidays! 
>   Linus Björnstam
> Attachments:
> * 0001-Added-srfi-171-to-guile-under-the-module-name-srfi-s.patch
> * 0002-Added-documentation-and-tests-for-srfi-171.patch

0001-Added-proper-copyright-to-srfi-171.patch
Description: Binary data


[PATCH] Add srfi-171 to guile

2019-12-22 Thread Linus Björnstam
Hi there!

This is a patch to add srfi-171 (transducers) to guile. 

It adds the srfi implementation, a guile-specific extension (tfold and tbatch 
which can be used to generalize things like tsegment), documentation (the whole 
srfi document plus additions into srfi-modules.texi) and tests. 

I have built it successfully on the latest master. This would be my first ever 
commit to a project I did not start myself, with the added bonus that I have no 
idea of how git works. Be kind :)

Happy holidays! 
  Linus Björnstam

0001-Added-srfi-171-to-guile-under-the-module-name-srfi-s.patch
Description: Binary data


0002-Added-documentation-and-tests-for-srfi-171.patch
Description: Binary data


Re: landed r7rs support

2019-11-17 Thread Linus Björnstam


Wow! Great job! 

The text about the standards process is probably going to annoy people since it 
does not mention the division between r7rs small and large :)

last time I checked, r7rs large was on path to become a much larger language 
than common lisp, and the goal the whole time was a large and a small language.
-- 
  Linus Björnstam

On Sun, 17 Nov 2019, at 15:44, Andy Wingo wrote:
> Hey all :)
> 
> Just a little heads-up that I just landed R7RS support.  Thanks to Göran
> Weinholt for akku-scm (https://gitlab.com/akkuscm/akku-r7rs/) and
> OKUMURA Yuki for yuni (https://github.com/okuoku/yuni), off of which
> some of these files were based.  (These projects are public domain /
> CC0).
> 
> The library syntax for R7RS is a subset of R6RS, so to use R7RS you just
> (import (scheme base)) and off you go.  As with R6RS also, there are
> some small lexical incompatibilities regarding hex escapes; see "R7RS
> Incompatibilities" in the manual.  Also there is a --r7rs command-line
> option.
> 
> Cheers,
> 
> Andy
> 
>



Re: conflicts in the gnu project now affect guile

2019-10-16 Thread Linus Björnstam
Hi Andy!

Your work (and amazing blog) and the wonderful work by the GUIX team is what 
brought me to guile. I don't have any I'll feelings towards Mark (I have 
appreciated his support on the mailing list many times), but I will follow 
Guile wherever you and Ludo take it, inside or outside the GNU project.

I am but a lowly hobby programmer (who found a home in scheme) soI don't think 
I can contribute much in either case, but if financial support for hosting is 
needed I can contribute to that. Apart from trying my best to help people in 
the IRC channel.


Thank you for your work.
-- 
  Linus Björnstam

On Wed, 16 Oct 2019, at 15:14, Andy Wingo wrote:
> Hello all,
> 
> In the last few weeks, a conversation among GNU maintainers that has
> been simmering for years burst into public.  For a while it resubmerged
> into private GNU lists, but now it has resurfaced to affect the Guile
> project.
> 
> Just for background information, I wrote about my thoughts here:
> 
>   https://wingolog.org/archives/2019/10/08/thoughts-on-rms-and-gnu
> 
> The summary is that, like many people in GNU, I have long treated
> Richard Stallman not as a hero, not as a leader, but rather a "missing
> stair" (https://en.wikipedia.org/wiki/Missing_stair) that one has to
> route around.  This approach was never very inclusive -- if you don't
> have much experience in GNU, it's possible to not know about it, and to
> fall in the hole yourself.  On the other hand if you know of RMS but not
> Guile, you might think that Guile developers support RMS.
> 
> However, recent events made me realize this approach was not only unfair
> to newcomers, but unjust as well, as by continuing to work on GNU and
> not saying anything, I was both lending unmerited prestige to RMS,
> enabling his creepy behavior towards women, and additionally, enabling
> his apparent pedophilia-advocacy.
> 
> Regarding this latter point, I wasn't really aware that this was a view
> RMS was promoting, but I am ashamed to admit that I had heard rumors
> that Richard publically advocated sex between adults and teenagers,
> defended sexual harassers, and questioned the experience of victims of
> sexual assault, and I preferred not to listen.  Looking again, and I
> think Richard's web site speaks for itself:
> 
>   
> https://web.archive.org/web/20170612074722/http://stallman.org/archives/2017-mar-jun.html#26_May_2017_(Prudish_ignorantism)
>   
> https://web.archive.org/web/20180131020215/https://stallman.org/archives/2017-jul-oct.html#29_October_2017_(Pestering_women)
>   
> https://web.archive.org/web/20180104112431/https://www.stallman.org/archives/2017-nov-feb.html#27_November_2017_(Roy_Moore's_relationships)
>   
> https://web.archive.org/web/20180509120046/https://stallman.org/archives/2018-mar-jun.html#30_April_2018_(UN_peacekeepers_in_South_Sudan)
>   
> https://web.archive.org/web/20180911075211/https://www.stallman.org/archives/2018-jul-oct.html#17_July_2018_(The_bullshitter's_flirting)
>   
> https://web.archive.org/web/20180911075211/https://www.stallman.org/archives/2018-jul-oct.html#21_August_2018_(Age_and_attraction)
>   
> https://web.archive.org/web/20180924231708/https://stallman.org/archives/2018-jul-oct.html#23_September_2018_(Cody_Wilson)
>   
> https://web.archive.org/web/20181113161736/https://www.stallman.org/archives/2018-sep-dec.html#6_November_2018_(Sex_according_to_porn)
>   
> https://web.archive.org/web/20190325024048/https://stallman.org/archives/2019-jan-apr.html#14_February_2019_(Respecting_peoples_right_to_say_no)
>   
> https://www.stallman.org/archives/2019-may-aug.html#11_June_2019_(Stretching_meaning_of_terms)
>   
> https://web.archive.org/web/20190801201704/https://stallman.org/archives/2019-may-aug.html#12_June_2019_(Declining_sex_rates)
>   
> https://web.archive.org/web/20190801201704/https://stallman.org/archives/2019-may-aug.html#30_July_2019_(Al_Franken)
>   
> https://web.archive.org/web/20190903050208/https://stallman.org/archives/2019-jul-oct.html#27_August_2019_(Me-too_frenzy)
> 
> Anyway.  So far, so GNU.  A couple weeks ago I thought it an opportune
> moment to declare publicly the views that I have long held privately:
> that I do not consider RMS to be the leader of GNU, and that GNU
> maintainers and other developers with a stake in the project should
> organize to fill the void.
> 
>*  *  *
> 
> I pause here to mention that you may not agree with this perspective and
> that is fine.  There are many ways that we can continue to work together
> while this discussion plays out.  Part of the purpose of this mail
> though is to make it clear that there are differences of opinion and
> that the GNU project is in flux.
&