From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Israelsson Tampe Newsgroups: gmane.lisp.guile.user Subject: Re: return macro Date: Thu, 30 Sep 2021 11:18:23 +0200 Message-ID: References: <1142492b-16bf-7181-8d93-38bfc2d3c748@gmail.com> <84359060abff196e59ae99c28dda37f8ac4b56ae.camel@riseup.net> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="14256"; mail-complaints-to="usenet@ciao.gmane.io" Cc: guile-user To: Damien Mattei Original-X-From: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Thu Sep 30 11:18:56 2021 Return-path: Envelope-to: guile-user@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mVsDP-0003XT-U6 for guile-user@m.gmane-mx.org; Thu, 30 Sep 2021 11:18:56 +0200 Original-Received: from localhost ([::1]:35374 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mVsDO-0002vd-Qv for guile-user@m.gmane-mx.org; Thu, 30 Sep 2021 05:18:54 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:59730) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mVsD9-0002nk-9d for guile-user@gnu.org; Thu, 30 Sep 2021 05:18:39 -0400 Original-Received: from mail-vk1-xa31.google.com ([2607:f8b0:4864:20::a31]:46959) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mVsD6-0005Ij-RI for guile-user@gnu.org; Thu, 30 Sep 2021 05:18:38 -0400 Original-Received: by mail-vk1-xa31.google.com with SMTP id b67so2479349vkb.13 for ; Thu, 30 Sep 2021 02:18:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=G1OVIptkMWfFyhan5ng5iV5eTzfQjmWkYv0Q3pCtN6s=; b=P937wcMrbT4e9ejuUYJia7dwIOyMpn22R3NWRWr925QA5utLcK3FhL8dD7Olkplud5 ghTnxHalSQr8q74uZk+CA7F797wGxJK9XGAri+kfobK5Bo0MHWvyiJ40VpHHMb46jpLh NI2hZm4erg64X3PFpJQgfG8mjAllLIXJdzHuMiY/j7kzr1dClTXp9BqLDWztmMfiqTLs TCJfpXMeyHMm5Rbd0o7c/npQ1+KMIrZint/I4LRaUVkw6P3cG/W8LV5eTfEmvh1ZQzX+ 15IRq0HgduRNDFTk+dwW/eaxiuk6kF2U5lq6Jaf5gCGD45MOYFllndvBl8bgPbxxiMJd FozQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=G1OVIptkMWfFyhan5ng5iV5eTzfQjmWkYv0Q3pCtN6s=; b=Xdxi89ciN7e6IxH2EYnk4M9O8aBX4X3bs3cz/rYAZnk/DNwafN7nC58rA+xaYbn/jS 3vrlCM7z2vifkbFZijfXFc0mF7qx0KdVtBrnRF6jBPcf2UNXu6evB5MTYNjkF8RFl+tM 6V9KePQkWndRSBpaQbGc/p7vB9lKiDSHSAUtPVcoH5YGLvXF6Xb4F0PfIukd/KwkjZR6 wWMip68AXcts4iN4KaEGxAwSAdefQEDZoJsRcALCs6D2EitV8gPp9/PVaE0FJJuixyNk IyGJrJtwNjZjZH5J+hF1JQNArik9bWF9IBvTsJ7nI9suYvBEvUQgRZXlyFtOn7Ey74si GFIg== X-Gm-Message-State: AOAM532sCtlRkzdWfNwf9iVHg6vtS8WIoVHXsk5Ayj2+BAKwEXf655C7 tHXhonod8rf+Q82sJ7gxSjDTTj4FhZ47gln+Eyc= X-Google-Smtp-Source: ABdhPJzO0VPy5ULnqRKj4DNBML5GluR6yCSQcOzWQ7DstFLp5SynH20xDyF1sJO2SNE9oxfTvnL9pIgrfHXoggOtOGY= X-Received: by 2002:a1f:2e57:: with SMTP id u84mr2028700vku.16.1632993514655; Thu, 30 Sep 2021 02:18:34 -0700 (PDT) In-Reply-To: Received-SPF: pass client-ip=2607:f8b0:4864:20::a31; envelope-from=stefan.itampe@gmail.com; helo=mail-vk1-xa31.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Content-Filtered-By: Mailman/MimeDel 2.1.23 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-mx.org@gnu.org Original-Sender: "guile-user" Xref: news.gmane.io gmane.lisp.guile.user:17789 Archived-At: used write a lambda using it prepending a ,opt and you will see what the macros expand to like ,opt (lambda (x) (let/ec ret (when x (ret x)) (+ x x))) On Thu, Sep 30, 2021 at 10:46 AM Damien Mattei wrote: > i do not remember well the technic of this commented code, in this case > note that it is 'break' keyword that cause the current continuation being > called and escaping from the loop to the continuing code... > there is no 'return' here but 'break'. > Damien > > On Thu, Sep 30, 2021 at 5:38 AM adriano wrote: > > > Il giorno lun, 28/06/2021 alle 03.15 +0200, Taylan Kammer ha scritto: > > > On 28.06.2021 01:10, Damien Mattei wrote: > > > > hi, > > > > > > > > i wanted to create a macro that is used like a function definition > > > > and > > > > allow return using call/cc: > > > > > > > > (define-syntax def > > > > (syntax-rules (return) > > > > ((_ (name args ...) body body* ...) > > > > (define name (lambda (args ...) > > > > (call/cc (lambda (return) body body* ...))))) > > > > ((_ name expr) (define name expr)))) > > > > > > > > unfortunaly i got error: > > > > > > > > scheme@(guile-user)> (def (test x) (cond ((= x 3) 7) ((= x 2) > > > > (return 5)) > > > > (else 3))) > > > > ;;; :2:42: warning: possibly unbound variable `return' > > > > scheme@(guile-user)> (test 2) > > > > ice-9/boot-9.scm:1685:16: In procedure raise-exception: > > > > Unbound variable: return > > > > > > > > > > > > any idea? > > > > > > Hi Damien, > > > > > > This is because of the "hygiene" rule of Scheme, where the notion of > > > "lexical > > > scope" is taken very seriously: for an identifier to be bound, it > > > must be > > > visible in the lexical (textual) surroundings where it has been > > > bound. > > > > > > So for instance, in the following example code: > > > > > > (def (test x) > > > (cond > > > ((= x 3) (return 7)) > > > ((= x 2) (return 5)))) > > > > > > We can't see a binding for "return" anywhere in the text, therefore > > > it cannot > > > be bound. > > > > > > This is good "default" behavior because it makes code more flexible > > > and easier > > > to understand. > > > > > > An easy way of overcoming this issue is to let the user explicitly > > > name the > > > return identifier however they like: > > > > > > (define-syntax def > > > (syntax-rules () > > > ((_ (name ret arg ...) body body* ...) > > > (define (name arg ...) > > > (call/cc (lambda (ret) body body* ...)))))) > > > > > > Now you could define: > > > > > > (def (test return x) > > > (cond > > > ((= x 3) (return 7)) > > > ((= x 2) (return 5)))) > > > > > > Or for instance: > > > > > > (def (test blubba x) > > > (cond > > > ((= x 3) (blubba 7)) > > > ((= x 2) (blubba 5)))) > > > > > > However, sometimes you're sure that you want to make an implicit > > > binding for > > > an identifier, and for those cases you need to write an "unhygienic" > > > macro > > > which can be achieved with the more complex macro system "syntax- > > > case". > > > > > > Here's how your desired macro could be defined. I will use > > > identifiers like > > > "" just for easier readability; they don't have any special > > > meaning: > > > > > > (define-syntax def > > > (lambda (stx) > > > (syntax-case stx () > > > ((_ ( ...) * ...) > > > (let ((ret-id (datum->syntax stx 'return))) > > > #`(define ( ...) > > > (call/cc (lambda (#,ret-id) * ...)))))))) > > > > > > There's a few things here to take note of: > > > > > > - Unlike with syntax-rules, the syntax-case is contained in a lambda > > > which > > > takes a single argument: a "syntax object" which is passed to > > > syntax-case > > > > > > - Unlike with syntax-rules, the "body" of the macro (where it begins > > > with a > > > 'let') is not immediately part of the generated code; that 'let' is > > > actually > > > executed during compile-time. The body of the macro must result in > > > an > > > object of the type "syntax object" that represents the generated > > > code. > > > > > > - You see that I define a variable called "ret-id" which I bind to > > > the result > > > of the expression: > > > > > > (datum->syntax stx 'return) > > > > > > which means "create a syntax object in the same lexical environment > > > as stx, > > > and is represented by the symbol 'return'." > > > > > > - The actual code generation begins within the #`(...) which is a > > > shorthand > > > for (quasisyntax (...)) just like '(...) is short for (quote > > > (...)). The > > > result of a quasisyntax expression is a syntax object. Basically, > > > it's the > > > most convenient way of creating a syntax object, but like syntax- > > > rules it's > > > also hygienic by default and you need to insert "unhygienic" syntax > > > objects > > > into it explicitly. > > > > > > - Within the quasisyntax, I use #,ret-id which is short for (unsyntax > > > ret-id) > > > to inject the unhygienic syntax object that holds the symbol > > > 'return' into > > > the generated code. > > > > > > For someone used to macros in the Common Lisp or Elisp style, this > > > may seem > > > over-complicated. It's the cost of the "hygienic by default" > > > behavior. > > > > > > By the way I assume that you're just toying around with the language > > > to learn. > > > If you were thinking of using a 'def' macro like this in real code, I > > > would > > > discourage it because there's already a built-in mechanism that > > > allows the > > > programmer something very similar, called 'let/ec': > > > > > > (import (ice-9 control)) > > > > > > (define (test x) > > > (let/ec return > > > (cond > > > ((= x 3) (return 7)) > > > ((= x 2) (return 5))))) > > > > > > > > What does this return (defined with let/ec) do ? > > > > In the orevious versions I could see the call to call/cc so I could > > (somewhat) figure out the "jump" imlpied by calling return > > > > But in this last case, where is the return behaviour defined ? > > > > > > > > >