This succeeds if obj matches the pattern p::Point, declaring p to be the value of obj coerced to a Point.
This is integrated with Kawa's static type-checking/inference.
Clojure to the rescue ... again. Honestly, I can't fathom why Clojure isn't up there with the most popular languages. Paul Graham was right when he described it, well Lisp, as a secret weapon.
I think Clojure is not statically typed? which is a big disadvantage, and also syntax is very different from current mainstream languages, so even more effort to learn is required.
When type checking is needed, I find the Truss library* does the trick quite well.
As for the syntax, there is very little, which can make it a harder lift but once you have the hang of it you won't deal with the issues identified in the parent comment.
JS and Python are not statically typed, or PHP for that matter, but it hasn't stopped JS and Python topping the popularity list year on year nor did PHP stop Facebook from world domination.
i would imagine the idiomatic clojure to do this is to convert the `p` into a bean using `clojure.core/bean`
but if it is a java record class, then there's currently no standard library way, since it's not a bean (getter/setter naming of properties). You'd have to write custom code for it, which sucks.
Note that we are using pattern matching here to recognize and rewrite this case. In return we will obtain better code from pattern matching:
$ make
TXR stdlib/compiler.tl -> stdlib/compiler.tlo
$ ./txr
This is the TXR Lisp interactive listener of TXR 291.
Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet.
TXR is not a toy, but should be kept within easy reach of children.
1> (flow '(if-match @(struct point x @x y @y) (new (point 1 2))
(prinl (+ x y)))
expand
prinl
compile-toplevel
disassemble)
(let ((#:g0024 (struct-from-args 'point 1 2)))
(let* (#:result-0028
x y)
(if (if (subtypep (typeof #:g0024) ;; this hasn't changed, of course
'point)
(let ((#:x0026 (slot #:g0024 'x))
(#:y0027 (slot #:g0024 'y)))
(sys:setq x #:x0026)
(sys:setq y #:y0027)
(sys:setq #:result-0028
(prinl (+ x y)))
t))
#:result-0028
())))
** expr-1:1: warning: if-match: no such struct type: point
** expr-1:1: warning: new: point does not name a struct type
data:
0: point
1: 1
2: 2
3: x
4: y
syms:
0: struct-from-args
1: typep ;;; no mention of subtypep here any more!
2: slot
3: prinl
4: sys:b+
code:
0: 2003000E gcall t14 0 d0 d1 d2
1: 04000000
2: 04020401
3: 20020002 gcall t2 1 t14 d0
4: 000E0001
5: 00000400
6: 38000014 if t2 20
7: 00000002
8: 2002000A gcall t10 2 t14 d3
9: 000E0002
10: 00000403
11: 20020009 gcall t9 2 t14 d4
12: 000E0002
13: 00000404
14: 20020006 gcall t6 4 t10 t9
15: 000A0004
16: 00000009
17: 2001000D gcall t13 3 t6
18: 00060003
19: 1000000D end t13
20: 10000000 end nil
instruction count:
9 ;; down by one
#<sys:vm-desc: 92c94d0>
Per_Bothner|2 years ago
https://www.gnu.org/software/kawa/Conditionals.html
cutler|2 years ago
riku_iki|2 years ago
nkh|2 years ago
As for the syntax, there is very little, which can make it a harder lift but once you have the hang of it you won't deal with the issues identified in the parent comment.
* https://github.com/taoensso/truss
cutler|2 years ago
chii|2 years ago
but if it is a java record class, then there's currently no standard library way, since it's not a bean (getter/setter naming of properties). You'd have to write custom code for it, which sucks.
kazinator|2 years ago
Using quasiquote-style pattern:
Or using @(struct ...) pattern operator: All done with macros. Expansion, compilation, disassembly: I see this is doing something silly: (subtypep (typeof x) y) is just (typep x y), but costs an extra gcall instruction.Either the pattern matcher should do this, or the compiler should have that as an algebraic reduction, or both.
Let's do the compiler for fun:
Note that we are using pattern matching here to recognize and rewrite this case. In return we will obtain better code from pattern matching: Ship it!