libera/#lisp - IRC Chatlog
Search
9:56:50
rendar
let's consider this impl of eval() in python: https://github.com/fluentpython/lispy/blob/main/mylis/mylis_3/evaluator.py
9:59:50
jackdaniel
on the other hand (funcall [foo] a-list-with-elements) calls foo with exactly one argument
10:00:55
jackdaniel
for no particular reason; just to make the function distinct from other arguments
10:05:59
jcowan
Note also that apply can take additional arguments before the list which are prepended to it, so (funcall proc x y) is (apply proc x y '()).
10:14:00
rendar
this is why a binary function such as +, takes more args, and so we can have (+ 1 1 1 1)=4, because of apply..
10:15:56
jackdaniel
i.e in common lisp (defun foo (a &rest remaining-args) …) creates the function that takes a variable number of arguments
10:16:13
jackdaniel
funcall and apply are only means to deliver arguments to the function, they have nothing to do with the function arity
10:57:56
aeth
What you do with + depends on what you're targeting... A Lisp-to-Lisp compiler or a Lisp-to-Lisp interpreter (just differing dialects) doesn't have to convert it to binary because you can just ultimately produce or call (+ x y z u v w).
10:58:36
aeth
Targeting machine code or a simple interpreter bytecode or another programming language probably has to turn (+ x y z u v w) into (((((x + y) + z) + u) + v) + w)
11:00:24
aeth
Note that in a Lisp, (+) is 0 and (*) is 1 and (+ x) and (* x) produce the thing itself. So if you do some fancy transformation you have to handle the 0-length and 1-length input cases before you turn it into binary operations
11:00:58
aeth
(/) and (-) are probably invalid, while (/ x) is 1/x and (- x) is the unary negation, which if you're lazy you can just turn into (- 0 x)
11:01:58
aeth
or, if you want to mess with people, combine this knowledge and turn (- x) into (- (+) x) and (/ x) into (/ (*) x)
11:03:19
aeth
It also becomes clear that one of the first and easiest optimizations you can do is handling *, +, /, and - (and perhaps a few others) in a special way if they're known at the function definition time to avoid some genericness
11:04:20
aeth
it also provides a reasonable default for macros (and for some higher order functions like perhaps #'reduce ?)
11:07:06
aeth
in mathematical Lisp, the limit constants are mutable and can be increased (but not lowered) during runtime
11:09:15
aeth
if you want to do something fancy with arguments, you would do (progn (incf call-arguments-limit) x) instead of x for all x that you use as an argument. :-p
11:09:49
jackdaniel
c.f https://sites.middlebury.edu/fyse1229pisapati/mathematical-work/potential-infinite-v-actual-infinite/
11:10:49
aeth
people say that mutable globals are bad for analysis of the program, but not if they're only monotonically increasing as I describe.
11:11:16
pjb
you could hook a CL implementation to a robotic asteroid mining chip factory, so that when you reach the memory boundary, you could collect some more materials and build more, without stopping your process.
11:12:05
pjb
The same factory could also be used to build star ships, for when you're done converting the solar system into an "unbounded" CL processor.
11:47:32
jcowan
Scheme has an optional feature called auto-forcing, by which a procedure that is not universally polymorphic (i.e. `*` but not `list`) can determine if any of its arguments are promises and force them.
11:49:37
jcowan
So for example (let ((p1 (http-get "foo")) (p2 (http-get "bar"))) (+ p1 p2 3)) would get two promise arguments (assuming http-get returns a promise) and force them, so that when both GET operations have completed the result is their sum plus 3 (a non-promise argument)
11:58:33
flatwhatson
(define (force-wrap fn) (lambda args (apply fn (map (lambda (x) (if (promise? x) (force x) x)) args))))