From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Damien Mattei Newsgroups: gmane.lisp.guile.user Subject: Re: define-typed: checking values on proc entry and exit Date: Tue, 21 May 2024 09:05:37 +0200 Message-ID: References: <871q6axg4s.fsf@web.de> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="6814"; mail-complaints-to="usenet@ciao.gmane.io" Cc: guile-user@gnu.org To: "Dr. Arne Babenhauserheide" Original-X-From: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Tue May 21 09:06:46 2024 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 1s9Ja9-0001Z8-Hc for guile-user@m.gmane-mx.org; Tue, 21 May 2024 09:06:45 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1s9JZO-0000Rg-Fu; Tue, 21 May 2024 03:05:58 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1s9JZM-0000RO-Mq for guile-user@gnu.org; Tue, 21 May 2024 03:05:56 -0400 Original-Received: from mail-ua1-x932.google.com ([2607:f8b0:4864:20::932]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1s9JZI-0007bF-Og for guile-user@gnu.org; Tue, 21 May 2024 03:05:56 -0400 Original-Received: by mail-ua1-x932.google.com with SMTP id a1e0cc1a2514c-7f74cca5a2bso1084218241.3 for ; Tue, 21 May 2024 00:05:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1716275151; x=1716879951; darn=gnu.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=Uo0mpjARLvfVGDnlmWhVYjosQr2Udxwa/20dr9QSJI4=; b=c/nZPnYsCtPPxMlhsVFAI4e/cSa/h2xjdqA+45+WW53D3ffdW3Lu1n5ACyna/w7eID 4TuljKJuDeSrWoBDvhcKKCch0bhzQevLt4F+zV+cOrLRDiPysAl/IkDNo8fiSP5Eys9u cgHHz8Bb+F0aq+AwC44AGhujxHXIdzlUGFsgE59bG9qgzacyXSwcdSQu9NqFF1Cg1w7R Ec+hB+NRpzoAbj7zZHZRHly5tm3kG97H0zK3eQjNZ8HudYzgNQY/ai9Lq0akHc19iBlv UhsgHDIM6/699GBM/y1KVHRqhnRLAxTr4Gd9rKCkFnvz7Lut76aQC4Lc4LWwpaC3Y0yP 7jdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1716275151; x=1716879951; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Uo0mpjARLvfVGDnlmWhVYjosQr2Udxwa/20dr9QSJI4=; b=UJbBbecI3y9AMhfMHKoHfUnVQVSSoV4QBYRu1HaSIFU/TZ0SsrGht3hWkoeEm82Z3U dwDBJXNSoPWNh+SR/XU9iVwnJFhB81YYlomyiqoAt/0qa0bRDnaDHJpW83OYX/AjZSaX cIQrwC2ugjxxtb8OybkPlOWI1nFRmbpRrZksXDGS2lpGfVfHysXQIn3BsicRVecM73pL D0urKrPMIQGCNnQhzvlo1pn4WsmzndjyG4bCOZTG1BxGE/cq/jq47MqmtXvokBanIHiN zxzxgOlpg0mAnYg7Gg/5SGVjhZfIAUPK8ZdG9QycvazMYJj+M8TL/Oa/2Z8/gtcH3s7f ELOw== X-Gm-Message-State: AOJu0YwygOm86P2drkFJ66puZI+7UGo9O9RDrjGEmZDz3Lz5S+1z5lA9 lN8TwbaeWYCT4w2UF9/loKb/xDa2ESqfXVtF1VhztVvSlv8qdZg/JoTKNIwhC5r+BmfPPYZ+2st kKgD5SSZQVUUkMtnRH0zYuhQvh3I= X-Google-Smtp-Source: AGHT+IHti9IcID8ZhiaonwfHycSJ+VbcXYWVry4Ny9Owp61phY/b0zvjB48Bm/f4Ce0sLQ6XeOYIK/e+XBrvAmFolFE= X-Received: by 2002:a05:6122:46a1:b0:4da:e777:a8e6 with SMTP id 71dfb90a1353d-4df88369931mr29718343e0c.14.1716275149248; Tue, 21 May 2024 00:05:49 -0700 (PDT) In-Reply-To: <871q6axg4s.fsf@web.de> Received-SPF: pass client-ip=2607:f8b0:4864:20::932; envelope-from=damien.mattei@gmail.com; helo=mail-ua1-x932.google.com X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.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, LOTS_OF_MONEY=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URI_DOTEDU=1 autolearn=no autolearn_force=no X-Spam_action: no action X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.29 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-bounces+guile-user=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.lisp.guile.user:19665 Archived-At: Hello, not sure to understand but does GOOPS (Guile object model) allow some sort of check to the argument but perhaps it is only inherent to the procedures of a 'class' in the object model? anyway if you are just interesting in type checking some procedure Scheme+ (ref: 1) that i currently still developing allow this when overloading procedures and operators as you specify a type as you by a list of predicates example: (number? number?) but rather than you i do not specify a return type as there is no way to check the value the procedure (example : (set! x (foo y)) will set will be put of a variable of same type as scheme is not typed (here who know the type of x?) If you call the overloaded procedure with not "declared" arguments it will display an error. It works both for procedure and "operators" even it is the same in scheme the implementation are different. it works like this for example: overloading some existing procedures: (use-modules (overload)) i overload length to accept both vector and string and still lists: (overload-existing-procedure length vector-length (vector?)) (overload-existing-procedure length string-length (string?)) use: scheme@(guile-user)> (length "abcde") $3 =3D 5 scheme@(guile-user)> (length '(1 2 3 4)) $4 =3D 4 scheme@(guile-user)> (length #(1 2 3)) $5 =3D 3 overload a non (already) existing procedure, i need to do it in 2 steps: first say i will define it later: (define-overload-procedure area) perheaps i should rename this declare-... instead of define-... then define the new procedures to compute area of square and rectangle: (define (surf-carre-parfait x) (* x x)) (define (surf-carre-long x y) (* x y)) note: in old Fran=C3=A7ais a "carr=C3=A9 long" (long square) is what we cal= l today a rectangle :-) (overload-procedure area surf-carre-parfait (number?)) (overload-procedure area surf-carre-long (number? number?)) tests: scheme@(guile-user)> (area 3.4) $1 =3D 11.559999999999999 scheme@(guile-user)> (area 2.3 4.5) $2 =3D 10.35 scheme@(guile-user)> (area "hello") ice-9/boot-9.scm:1685:16: In procedure raise-exception: overload "failed because procedure can not be applied to arguments list. procedure , arguments list =3D " *b ("hello") overloading an operator, for the sum of n lists: first define a procedure doing the job because i need to know it before overloading +: (define (add-n-lists . vn-lst) (implementation-add-n-lists vn-lst)) note here add-n-lists is just a wrapper to implementation-add-n-lists which will be defined later.... then use the overloading macro to overload the + operator: (overload-existing-n-arity-operator + add-n-lists (list? list?)) then of course implement really the sum of n lists: (define (implementation-add-n-lists vn-lst) {map-args <+ (cons + vn-lst)} (apply map map-args)) or : (define (implementation-add-n-lists vn-lst) (define map-args (cons + vn-lst)) (apply map map-args)) another example that multiply all elements of a list by a number: (define (mult-num-list k v) (map (=CE=BB (x) (* k x)) v)) (overload-existing-operator * mult-num-list (number? list?)) the system in action: (define t {3 * '(1 2 3) + '(4 5 6) + '(7 8 9)}) (display t) (newline) will give: (14 19 24) note: as * has precedence over + we first evaluate 3 * '(1 2 3) =3D '(3 6 9= ) and after add '(4 5 6) + '(7 8 9) i will not explain the implementation here, it is too long , it is at the limit of what scheme can do, for this reason implementation can differ from a scheme to another (i could use hash table in some implementation for example...and not with another scheme - racket is more strict) , it will work at the toplevel of a module and at REPL but for now you could not overload in a function - not interesting in fact) and because of the operator precedence, but all is in respect of scheme syntax rules, i'm uniformising between schemes.Things could be hard if you want to overload [ ] with SRFI 105 but it's work. The last stable version of code is available here : https://github.com/damien-mattei/Scheme-PLUS-for-Guile/blob/main/overload.s= cm 1 : https://github.com/damien-mattei/Scheme-PLUS-for-Guile/ Regard, Damien On Fri, May 10, 2024 at 9:48=E2=80=AFAM Dr. Arne Babenhauserheide wrote: > Hi, > > in #guile on IRC=C2=B9, old talked about Typed Racket so I thought whethe= r > that could be done with define-syntax-rule. So I created define-typed. > This is also on my website=C2=B2, but I wanted to share and discuss it he= re. > > I follow the format by [sph-sc], a Scheme to C compiler. It declares > types after the function definition like this: > > =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80 > =E2=94=82 (define (hello typed-world) (string? string?) > =E2=94=82 typed-world) > =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80 > > =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80 > =E2=94=82 (define-syntax-rule (define-typed (procname args ...) (ret? typ= es ...) > body ...) > =E2=94=82 (begin > =E2=94=82 (define (procname args ...) > =E2=94=82 ;; define a helper pro > =E2=94=82 (define (helper) > =E2=94=82 body ...) > =E2=94=82 ;; use a typecheck prefix for the arguments > =E2=94=82 (map (=CE=BB (type? argument) > =E2=94=82 (unless (type? argument) > =E2=94=82 (error "type error ~a ~a" type? argument))) > =E2=94=82 (list types ...) (list args ...) ) > =E2=94=82 ;; get the result > =E2=94=82 (let ((res (helper))) > =E2=94=82 ;; typecheck the result > =E2=94=82 (unless (ret? res) > =E2=94=82 (error "type error: return value ~a does not match ~a= " > =E2=94=82 res ret?)) > =E2=94=82 ;; return the result > =E2=94=82 res)) > =E2=94=82 ;; add procedure properties > =E2=94=82 (let ((helper (lambda (args ...) body ...))) > =E2=94=82 (set-procedure-properties! procname (procedure-properties= helper)) > =E2=94=82 ;; preserve the name > =E2=94=82 (set-procedure-property! procname 'name 'procname)))) > =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80 > > This supports most features of regular define like docstrings, procedure > properties, and so forth. > > =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80 > =E2=94=82 (define-typed (hello typed-world) (string? string?) > =E2=94=82 typed-world) > =E2=94=82 (hello "typed") > =E2=94=82 ;; =3D> "typed" > =E2=94=82 (hello 1337) > =E2=94=82 ;; =3D> type error ~a ~a # 1337 > =E2=94=82 (define-typed (hello typed-world) (string? string?) > =E2=94=82 "typed" > =E2=94=82 #((props)) > =E2=94=82 typed-world) > =E2=94=82 (procedure-properties hello) > =E2=94=82 ;; =3D> ((name . hello) (documentation . "typed") (props)) > =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80 > > This should automate some of the guards of [Optimizing Guile Scheme], so > the compiler can optimize more (i.e. if you check for `real?') but keep > in mind that these checks are not free: only typecheck outside tight > loops. > > They provide a type boundary instead of forcing explicit static typing. > > Also you can do more advanced checks by providing your own test > procedures and validating your API more elegantly, but these then won=E2= =80=99t > help the compiler produce faster code. > > But keep in mind that this does not actually provide static program > analysis like while-you-write type checks. It=E2=80=99s simply [syntactic= sugar] > for a boundary through which only allowed values can pass. Thanks to > program flow analysis by the just-in-time compiler, it can make your > code faster, but that=E2=80=99s not guaranteed. It may be useful for your= next > API definition. > > My question now: do you have an idea for a better name than > define-typed? > > > [sph-sc] > > [Optimizing Guile Scheme] > > > [syntactic sugar] > < > http://www.phyast.pitt.edu/~micheles/scheme/scheme12.html#are-macros-just= -syntactic-sugar > > > > > =C2=B9 https://web.libera.chat/?nick=3DWisp|?#guile > =C2=B2 https://www.draketo.de/software/guile-snippets#define-typed > > > Best wishes, > Arne >