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 19:32:59 +0100 Message-ID: <20190707193259.434e1a816c551ece292f45da@gmail.com> References: <5f08685b-be5b-e584-af54-9f4244039b1a@gmail.com> 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="174116"; mail-complaints-to="usenet@blaine.gmane.org" To: guile-user@gnu.org Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Sun Jul 07 20:33:26 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 1hkByV-000j5R-2l for guile-user@m.gmane.org; Sun, 07 Jul 2019 20:33:23 +0200 Original-Received: from localhost ([::1]:36504 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hkByU-0003ph-4x for guile-user@m.gmane.org; Sun, 07 Jul 2019 14:33:22 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:37719) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hkByC-0003ov-Qm for guile-user@gnu.org; Sun, 07 Jul 2019 14:33:06 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hkByB-0006Tt-IZ for guile-user@gnu.org; Sun, 07 Jul 2019 14:33:04 -0400 Original-Received: from mail-wm1-x330.google.com ([2a00:1450:4864:20::330]:37413) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hkByB-0006RV-Bj for guile-user@gnu.org; Sun, 07 Jul 2019 14:33:03 -0400 Original-Received: by mail-wm1-x330.google.com with SMTP id f17so14178902wme.2 for ; Sun, 07 Jul 2019 11:33:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:subject:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=jG62MBKGX/A05N5Rq8JWjNU0M/waF+MqPzhal5/WLI0=; b=poNPVzb7EravT1K4WGV6to2nqq3g2QEEHiBp6l1Y96R//vsWPVVZ4S/zbsHVThlIte N/beXZd+DQuFprwhvyAjz2gHII3mcD5wa93ukvXVX3YrOwrGJ5f9AoJV/zu1T7gxAegx pi4PhSJQP16ofmInAEvggXX99fGHNaPdgQoO29oAqFS4EOYokbHwylaQQa3paZhzuETM cFx1us/gHnK+TFvJTe3Su8dlMC4fvjndvEdiDYLmOrrRgRLcIZpblhP7IPlm5+v4joVC j1c3+okLyq7CKnrAWr3nm0DtZGsihD6sJ+O+e9yZLU+feDrJqgA3TBOZkFEdahiwYqyU UpRQ== 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:subject:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jG62MBKGX/A05N5Rq8JWjNU0M/waF+MqPzhal5/WLI0=; b=RtIkHSHBIMAiUuKs9pRng4KG3VAtesFbE03zhqXvIHfbOTqtzUZC+n1qrT+ezLr7u+ vBYq60KEvvxMQ/SdBiYyUm6S7PeW9Va8rinqH9PdVEzZt+c82GmwxjsOv/SHukkUFYC8 Doj69ftgHRGiLlyb+53Epz6wx+RYN3fXodvmgpfQta3Trpua2CpI/LidFxDMOcyj/yO8 5IAZjfJSXAs8fGe6wuqwJSVAZMk16DU0O3b/ACog24GOnGbEQskyICkwGokJPEUDPXhL ej7tcevLKg9pOkOMBuDqVDY3MJLsqFuTbNZgBeI+eUQOj3HDKrKBm6dkf1K67Kg2yWB8 EAHQ== X-Gm-Message-State: APjAAAXF1j6nqXwRX+yWo79CUVFebGEBrUY6OJGGs6k3SADUDUssiGei 2FtqljrCZIUwLYvyZjSSLbY5WfJ7 X-Google-Smtp-Source: APXvYqzFjC0DHvDaEJXi7xSOP1FpALiuFyxUXv0RR6TqOf/oUvlAkc+nnL23OjqofwikfdHEgAogtA== X-Received: by 2002:a1c:cfc5:: with SMTP id f188mr11867552wmg.24.1562524381023; Sun, 07 Jul 2019 11:33:01 -0700 (PDT) Original-Received: from dell.homenet ([2002:545c:977f:10:e914:12bc:631d:b899]) by smtp.gmail.com with ESMTPSA id x18sm13365331wmi.12.2019.07.07.11.32.59 for (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Sun, 07 Jul 2019 11:33:00 -0700 (PDT) Original-Received: from dell.homenet (localhost [127.0.0.1]) by dell.homenet (Postfix) with SMTP id 1E69D425CE3 for ; Sun, 7 Jul 2019 19:32:59 +0100 (BST) In-Reply-To: <5f08685b-be5b-e584-af54-9f4244039b1a@gmail.com> 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::330 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:15604 Archived-At: On Sun, 7 Jul 2019 12:42:03 +0200 Zelphir Kaltstahl wrote: > Hi Guile Users! > > I recently looked at some online course about Elixir and saw an elegant > use of pipes (the operator `|>` in Elixir). Then I remembered, that in > Racket there are so called threading macros, which seem to accomplish > the same: > > https://github.com/lexi-lambda/threading/blob/master/threading-lib/threading/main.rkt > > I also searched around for tutorials or explanations on how to write > these macros. Sometimes I found excellent documenation in the Chicken > Scheme wiki, so I checked there: > > https://wiki.call-cc.org/eggref/5/pipes > > However, I would like to use a threading macro or pipes in Guile. I am > seeing these options: > > (1) I could start trying to translate the Racket version to Guile, maybe > it would work easily, maybe it uses Racket specific macro stuff, I don't > know. However, I am not sure I would learn how the macros actually work. > Maybe I would. > > (2) I could start from zero and try to implement the pipes I saw in the > online course about Elixir. > > (3) Maybe something already exists in Guile, that I am unaware of and > could not find through searching. Maybe there are even more names for pipes. > > So my questions are: > > (1) Does something already exist? > > (2) Would translating the Racket version be an easy thing to do, or is > there something in there, that cannot so easily be achieved with > syntax-parse, syntax-case and the likes? (For someone who rarely touches > macros and does not have a lot experience writing them.) 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. The syntax of the -> macro is like this: (-> (+ 3 4 5) (- 18) (format #t "~A\n")) The first expression in the '->' block is evaluated, and its value is passed as the last (or only) argument of the following expression, and so on. Each expression after the first one must be a function application (the first one can be either a function application or a value). The applied function comprising each expression after the first one appears to be curried, but in fact there is no currying, nor any runtime overhead at all. The above example code is expanded into the following scheme form: (format #t "~A\n" (- 18 (+ 3 4 5))) You can use it with a monadic bind (or applicative mapping) if you want so as to behave in a similar way to the >>= operator, but such things have little use in scheme in my opinion. (I can however provide a simple example of that if you think it would be interesting.) Chris