From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Linas Vepstas Newsgroups: gmane.lisp.guile.user Subject: Re: Pure (side-effect-free) calls into c/c++? Date: Sat, 11 Jan 2020 20:15:32 -0600 Message-ID: References: <7c06af2b-3ae7-d233-8ac9-5aabb9dff2de@gmail.com> Reply-To: linasvepstas@gmail.com Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="47173"; mail-complaints-to="usenet@blaine.gmane.org" Cc: Guile User To: Taylan Kammer Original-X-From: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Sun Jan 12 03:20:13 2020 Return-path: Envelope-to: guile-user@m.gmane-mx.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 1iqSnN-000opP-QW for guile-user@m.gmane-mx.org; Sun, 12 Jan 2020 03:16:05 +0100 Original-Received: from localhost ([::1]:34550 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iqSnM-0001Sk-LP for guile-user@m.gmane-mx.org; Sat, 11 Jan 2020 21:16:04 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:58249) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iqSnB-0001SR-3X for guile-user@gnu.org; Sat, 11 Jan 2020 21:15:55 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iqSn7-00070j-19 for guile-user@gnu.org; Sat, 11 Jan 2020 21:15:51 -0500 Original-Received: from mail-lf1-x129.google.com ([2a00:1450:4864:20::129]:37917) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iqSn5-0006wT-66 for guile-user@gnu.org; Sat, 11 Jan 2020 21:15:48 -0500 Original-Received: by mail-lf1-x129.google.com with SMTP id r14so4383169lfm.5 for ; Sat, 11 Jan 2020 18:15:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:reply-to:from:date:message-id :subject:to:cc; bh=v9MiDR4Jwr9oQiDLEPbduiSWnf4fc9NpssOlmhvrBrY=; b=STABIhxyBg1qu65cABYw+hlpAOScz/qLACTyh8uSkOzQO6WP2SzN4QxZNcB+jdj9YG VpqPLYi3cxyH8EDaK8fsUcYu4JH8R/EPF7llKSeiAFWUgv5Y6cPTQ0EO6kD2wp5/dGU+ CoDnZ8921z7duRl+l8hHILR4odgfJ4uOEZ5N8ogGPiF+kUMrWNKoFRizKVhQF/nhDEbV Ppkoo6qH0aOLyquIgLu6Nr/WZVBPEnZ8sPfsuKYFcICfSYPrretmwhCkSadMpRaeEybY ssAg6PoLXxpxKXoEoJHlorh9YVJnwqUG8BTGKQcKVexCXjy++eOnYq+0rA9sxybYjm4S ACCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:reply-to :from:date:message-id:subject:to:cc; bh=v9MiDR4Jwr9oQiDLEPbduiSWnf4fc9NpssOlmhvrBrY=; b=nkYAAHP7eKV/601wvm0+TpKk8eZr/lSVbpGnfDaEb5RO7r9QhxO1/10hS72Xq+iMa9 UjUkQZyd4BUwqCUn5P+NIf76UMhsgI0rXkTJjTXPRIVg4nluRFKz/Ms1T441/4c0XbxD 3jkDZ5HuNoRGC6UUxdvACTFvXjgN97EZhRYRY4LRHeIsrBVhGnTP+bv21XYXWC7FRtqc OvgO0rwh+nsJhHcx+x+lJEQ1BOT4I7OzDdq6IkwtRVz+SqKze/FMP6R5gTe7U/ZI+vN9 cPW7kEzdXeiCHBcBWC4rVPsbPjOcvQ45sY9/nclAZmmIfNC/B81rhmAaI6TMDlg2GYo2 wekg== X-Gm-Message-State: APjAAAVETTWKWz1nEPdcx/jSEYSXqPaUMksHr1+WU93SuODNLnsxy+rN VSMm3e/z3rZX4EsN4Wi7FqAO2O+ywCgOkAJDjK4= X-Google-Smtp-Source: APXvYqwcRuD/gkG0fUwxusrBDgqG8tezRq9zJBPKzvGjR898vtv10sXNAQKYIrnGME2ulOOiLEs5yuCwWBfLEIeuZzo= X-Received: by 2002:a19:5f58:: with SMTP id a24mr6445762lfj.9.1578795344146; Sat, 11 Jan 2020 18:15:44 -0800 (PST) In-Reply-To: <7c06af2b-3ae7-d233-8ac9-5aabb9dff2de@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::129 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.org gmane.lisp.guile.user:16036 Archived-At: Thanks Taylan, gmail is on the fritz lately and doesn't show replies until after I post; let me read what you wrote and ponder. ~~~ On Sat, Jan 11, 2020 at 3:56 PM Taylan Kammer wrote: > On 11.01.2020 19:52, Linas Vepstas wrote: > > Or, thinking aloud a bit: boxes and symbols.... > > > > So, for example, if I was able to tell apart calls (f 42) from calls (f > x) > > where x is a "symbol" (or "variable", *see below*) referencing an > integer, > > then, for the former case, I could create a new symbol (in guile) and > > attach it to a box, fill that box with whatever (f 42) would have > returned. > > Thence-forward, any call site in the guile code that had (f 42) in it > would > > get replaced by the symbol (or the unboxed value)... > > > > At the moment, I don't know how to tell apart 42, the literal number, > from > > x, a symbol that references a number. (Somehow, I can't make symbol? work > > ...) I also don't know how to "edit" the call site (the cell, the box?) > > that has (f 42) as the call-target, and replace it by a constant (or a > > boxed constant). > > > > But my naive thinking fails: > > (define x 0) > > (symbol? x) => #f > > (variable? x) => #f > > > > So I guess that x is not a symbol, from the guile point of view!? This > is > > .. confusing. What is x, then, if not a symbol? > > The issue here is that the expression "(symbol? x)" first evaluates the > expressions "symbol?" and "x" and then uses their values to go on. So > it ends up being: > > ( ) > > So by the time the procedure behind "symbol?" is called, it neither > knows that it was called "symbol?" nor does it know that the value it > received, i.e. the integer 0, came from a variable called "x". > > What you want to do is delve down to the macro layer so to say, by using > "define-syntax" and ideally "syntax-case". > > Here's a demonstration: > > (define-syntax symbol-syntax? > (lambda (stx) > (syntax-case stx () > ((_ x) > (if (symbol? (syntax->datum #'x)) > #'(display "yep\n") > #'(display "nope\n")))))) > > scheme> (symbol-syntax? blah) > yep > scheme> (symbol-syntax? (blah)) > nope > > What happens here is the following. Going through it part by part. > > (define-syntax symbol-syntax? > (lambda (stx) > ... > > You register a procedure (lambda (stx) ...) as a macro which you bind to > "symbol-syntax?". > > Now the expression "(symbol-syntax? blah)" will not be evaluated in the > regular fashion, because Guile sees that "symbol-syntax?" is registered > as a macro. > > Instead of trying to get the values of "symbol-syntax?" and "blah" like > it happened with "(symbol? x)", this time Guile calls the procedure > registered with "symbol-syntax?" immediately, and passes it a "syntax > object" that represents the whole expression "(symbol-syntax? blah)". > (Not just the "blah" argument but the whole expression, don't ask why.) > > (syntax-case stx () > ((_ x) > ... > > Within the procedure, we use "syntax-case" to do pattern-matching on the > expression "(symbol-syntax? blah)" that is stored in the variable "stx". > > We know that the first thing in the expression is "symbol-syntax?" > because otherwise we wouldn't have been invoked in the first place, so > we want to ignore that, hence we use the pattern "(_ x)" which ignores > the first thing (via the underscore) and binds the second thing to "x". > That second thing is "blah" so "x" contains that now. > > (if (symbol? (syntax->datum #'x)) > ... > > Now "x" contains the element "blah" but to your probable surprise, it's > not a symbol but rather a syntax object. Thankfully we can just call > "syntax->datum" to get the corresponding data value, which is going to > be the symbol "blah". > > You're probably wondering why we wrote #'x instead of just x in our call > to "syntax->datum" and to be honest I'm not 100% clear on the reason to > this day, but it's how syntax-case expects you to use pattern variables. > You're never allowed to reference them "bare". > > #'(display "yep\n") > > Finally, we use #' to create a whole new syntax object, containing the > expression (display "yep\n"). That syntax object is the value returned > from our procedure, so Guile puts it where "(symbol-syntax? blah)" was. > > When you compile the code, all that actually ends up in the program is > "(display ...)" with no trace of the original "(symbol-syntax? ...)" > expression being left. That's what macros do; they replace code at > compile time and leave no trace of themselves. > > In the second call, "(symbol-syntax? (blah))", the pattern variable "x" > ends up containing a syntax object representing "(blah)", and calling > "syntax->datum" on that yields a list and not a symbol, hence we end up > returning '(display "nope\n")' from the macro. > > ---------- > > All that might be daunting at first but after a while it becomes > natural, and the power it gives the programmer is really like nothing > else. :-) > > What you intend to do, which is traverse through a whole lambda body and > find instances of "(f 42)" to replace them, might be a bit tricky. > Let's say you've written a macro "my-define" which does that, then > consider the following definition: > > (my-define (foo x) > (let ((f 42)) > (+ f x))) > > Now you probably don't want to turn that "(f 42)" into anything else, > because it's not really a call to your "f". > > I've never written a macro yet which does something like that, so I'm > not sure I can help, but I'm happy to respond to questions about the > general workings of the macro system. > > > - Taylan > -- cassette tapes - analog TV - film cameras - you