From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Chris Vine Newsgroups: gmane.lisp.guile.user Subject: Re: Threading / Pipe Macro Date: Sun, 7 Jul 2019 21:16:13 +0100 Message-ID: <20190707211613.4a8a637da93e592b4f737a7f@gmail.com> References: <5f08685b-be5b-e584-af54-9f4244039b1a@gmail.com> <20190707193259.434e1a816c551ece292f45da@gmail.com> <871rz1fxr7.fsf@netris.org> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="50133"; mail-complaints-to="usenet@blaine.gmane.org" Cc: guile-user@gnu.org To: Mark H Weaver Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Sun Jul 07 22:17:06 2019 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1hkDas-000Cwx-Jg for guile-user@m.gmane.org; Sun, 07 Jul 2019 22:17:06 +0200 Original-Received: from localhost ([::1]:36926 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hkDaq-0007rp-WD for guile-user@m.gmane.org; Sun, 07 Jul 2019 16:17:05 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:58512) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hkDaI-0007rb-EA for guile-user@gnu.org; Sun, 07 Jul 2019 16:16:32 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hkDaD-000760-M9 for guile-user@gnu.org; Sun, 07 Jul 2019 16:16:27 -0400 Original-Received: from mail-wm1-x32b.google.com ([2a00:1450:4864:20::32b]:52924) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hkDa7-000733-NX for guile-user@gnu.org; Sun, 07 Jul 2019 16:16:22 -0400 Original-Received: by mail-wm1-x32b.google.com with SMTP id s3so13723308wms.2 for ; Sun, 07 Jul 2019 13:16:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PksMMe+uH0CF6PiPBl3fF3MMOYKWngK9VGO57HeinkU=; b=RBlvGI4lRY+IgxYhK8vQ5zPDUqZFamSAbf0X28mVmeXYgm+lC/9Y9Y4L7BYx0La1Kn hPHusOtSR9xXrlYNQAkRX3y3GOTCOyuI8C5rwn+dl4LWMlbko4vD5Le8FmlvFUEz/Xcq Qwo9jmrMUq6ga45nbbrfWnvD96W6DXUZ9G7pcGD2y1r1uSPH7kuJ/rJ5FyxeZB17L+2r a/1VISpzTh/Vb/3kRTukMUT0+ur0JHZWUCLqqpsFOik0aFtBCTETynm5PeuEK9VQViky kasv7in7sIX6s2NdmQ8pTmAet38uWatFL53RDUtciUSkn5wEua2OAh3/BtZQBDXW+u/s 6Wag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=PksMMe+uH0CF6PiPBl3fF3MMOYKWngK9VGO57HeinkU=; b=pMYacBBJFLE2V67f+DUoFjUm4VvZ9DBMlY7Z7S3bRIc7KpcPKmiFaina0XfKumgX+C iYAdFebCpm6QQvEP1WCVCPfQKjTFpPiSEvcTY/W+PxLN5kgz1FGkKpZACpZXnhnwPWMh /XQx4yiklrpZrsD1L2BWyx6VfQRU9QV80H0HCLfTqQ/q/GsIC1Wir0afCWAkDjzT5h9P wYbG3+ckuQjj6Xw+dtHEv+j7O6BjItJA2zXrA/yT5Z7ahpIj0nYC1ESe0T/CP/gRE35K TqzXedGi1hlUOKR4ubZQq1FNAs4BHi8ma2+khFxkajn1mn1f9i2P1mkRT7KbSFwQK6DU deEw== X-Gm-Message-State: APjAAAUcnLcuvB8abr8xQmsyKyryFn0Zw2n9JcqxzHhCx58bh1bNmnRc BuyW0NlcsN7qvxr2jobd5LDDu17p X-Google-Smtp-Source: APXvYqwgQnaulU5VMambmj8SGMrpJKgwaFAKCtZ5U9jeZ+FYZ6943qyG57LwHTE4udZyWGEskAE81A== X-Received: by 2002:a1c:eb17:: with SMTP id j23mr13730237wmh.151.1562530575586; Sun, 07 Jul 2019 13:16:15 -0700 (PDT) Original-Received: from dell.homenet ([84.92.151.127]) by smtp.gmail.com with ESMTPSA id s25sm9731630wmc.21.2019.07.07.13.16.14 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Sun, 07 Jul 2019 13:16:14 -0700 (PDT) Original-Received: from dell.homenet (localhost [127.0.0.1]) by dell.homenet (Postfix) with SMTP id AEE11425CE3; Sun, 7 Jul 2019 21:16:13 +0100 (BST) In-Reply-To: <871rz1fxr7.fsf@netris.org> X-Mailer: Sylpheed 3.7.0 (GTK+ 2.24.32; x86_64-unknown-linux-gnu) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::32b X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Original-Sender: "guile-user" Xref: news.gmane.org gmane.lisp.guile.user:15607 Archived-At: On Sun, 07 Jul 2019 15:30:36 -0400 Mark H Weaver wrote: > Hi Chris, > > Chris Vine writes: > > > I have a pipeline macro which sort-of mimics ML's |> pipeline operator > > which I use a lot: > > > > (define-syntax -> > > (lambda (x) > > (syntax-case x () > > [(k exp0 . exps) > > (let* ([reversed (reverse (cons (syntax->datum #'exp0) > > (syntax->datum #'exps)))] > > [out (let loop ([first (car reversed)] > > [rest (cdr reversed)]) > > (if (null? rest) > > first > > (let ([func (car first)] > > [args (cdr first)]) > > (append `(,func ,@args) > > (list (loop (car rest) (cdrrest)))))))]) > > (datum->syntax #'k out))]))) > > > > Because all the macro does is to rearrange input forms, this is hygienic > > without the need to manipulate syntax objects - you can convert to a datum, > > rearrange and then convert back to a syntax object again, as above. > > This macro is *not* hygienic. The calls to 'syntax->datum' strip all of > the context information from the syntax objects, and then build a new > expression using raw S-expressions. The result is essentially the same > as if you used 'define-macro'. This results various problems. > > For example: > > --8<---------------cut here---------------start------------->8--- > scheme@(guile-user)> (define-syntax -> > (lambda (x) > (syntax-case x () > [(k exp0 . exps) > (let* ([reversed (reverse (cons (syntax->datum #'exp0) > (syntax->datum #'exps)))] > [out (let loop ([first (car reversed)] > [rest (cdr reversed)]) > (if (null? rest) > first > (let ([func (car first)] > [args (cdr first)]) > (append `(,func ,@args) > (list (loop (car rest) (cdr rest)))))))]) > (datum->syntax #'k out))]))) > scheme@(guile-user)> (define t 'global-t) > scheme@(guile-user)> (define-syntax-rule (foo x) > (-> x (format #t "[t=~A] ~A\n" t))) > scheme@(guile-user)> (let ((t 'inner-t)) (foo t)) > [t=global-t] global-t > $1 = #t > scheme@(guile-user)> > --8<---------------cut here---------------end--------------->8--- > > I recommend reformulating the -> macro using 'syntax-rules' as follows: > > --8<---------------cut here---------------start------------->8--- > scheme@(guile-user)> (define-syntax -> > (syntax-rules () > ((-> exp) > exp) > ((-> exp ... (op args ...)) > (op args ... (-> exp ...))))) > scheme@(guile-user)> (let ((t 'inner-t)) (foo t)) > [t=global-t] inner-t > $8 = #t > scheme@(guile-user)> > --8<---------------cut here---------------end--------------->8--- > > This macro is hygienic, and also easier to comprehend (IMO). Of course, > it could also be implemented using syntax-case. The key is to always > work with the syntax objects. > > Whenever you use 'syntax->datum' on expressions that are not purely > literals, you will be sacrificing hygiene. How strange. Both your and my macro gives 'global-t' when I test them, which is the result I would expect. (Maybe I am missing something here, but a result of 'inner-t' would seem to me to imply unhygiene.) However if I change my macro to manipulate syntax objects I do get 'inner-t' (define-syntax --> (lambda (x) (syntax-case x () [(_ exp0 exp1 ...) (let ([reversed (reverse #'(exp0 exp1 ...))]) (with-syntax ([out (let loop ([first (car reversed)] [rest (cdr reversed)]) (if (null? rest) first (syntax-case first () [(func arg0 ...) (append #'(func arg0 ...) (list (loop (car rest) (cdr rest))))])))]) #'out))]))) I need to think more about this and/or reproduce this later. This is with guile-2.2.6 by the way. Chris