Create a function with a function

Started by cameyo, March 30, 2021, 07:07:30 AM

Previous topic - Next topic

cameyo

Function to create a function with name and parameters:
(define (make-add name val)
  (let (f nil)
    (setq f (string "(define (" name " x) (+ " val " x))"))
    (setq name (eval-string f))
  name))

Creating a function
(make-add "sum-10" 10)
out: (lambda (x) (+ 10 x))

Using the created function
(sum-10 3)
out: 13

Do you know of another way (instead of using strings) to create a function with another function?

newBert

#1
Maybe this way, but it's not quite the same:

(define (make-adder x)
  (letex (x y)
    (fn (z) (+ y z))))
   
(setq add2 (make-adder 2))
(println (add2 4))
> 6
<r><I>>Bertrand<e></e></I> − <COLOR color=\"#808080\">><B>newLISP<e></e></B> v.10.7.6 64-bit <B>>on Linux<e></e></B> (<I>>Linux Mint 20.1<e></e></I>)<e></e></COLOR></r>

cameyo

#2
Thank you, but it doesn't works. The symbol y is not binded.

I am looking for the most suitable/fastest method of generating functions automatically (passing name of function and parameters).

newBert

#3
Oh my apologies! I reversed x and y (in `letex`) when transcribing... :/


(define (make-adder x)
  (letex (y x)
    (fn (z) (+ y z))))
   
(setq add2 (make-adder 2))
(println (add2 4))
; 6
<r><I>>Bertrand<e></e></I> − <COLOR color=\"#808080\">><B>newLISP<e></e></B> v.10.7.6 64-bit <B>>on Linux<e></e></B> (<I>>Linux Mint 20.1<e></e></I>)<e></e></COLOR></r>

cameyo

#4
It works.

But I would also need to pass the function name as a parameter, for example:
(make-adder "add10" 10)
Thanks again for the help

newBert

#5
So, maybe like this (probably improvable):

(define-macro (make-adder) (local (name val) (bind (args) true) (set (expand name 'name) (expand (lambda (x) (+ val x)) 'val))))

(make-adder (name 'add10) (val 10))
(println (add10 3))
; 13
<r><I>>Bertrand<e></e></I> − <COLOR color=\"#808080\">><B>newLISP<e></e></B> v.10.7.6 64-bit <B>>on Linux<e></e></B> (<I>>Linux Mint 20.1<e></e></I>)<e></e></COLOR></r>

newBert

#6
Sorry, I could not indent the previous code, because it caused an "internal server error" (?!)
<r><I>>Bertrand<e></e></I> − <COLOR color=\"#808080\">><B>newLISP<e></e></B> v.10.7.6 64-bit <B>>on Linux<e></e></B> (<I>>Linux Mint 20.1<e></e></I>)<e></e></COLOR></r>

cameyo

#7
Thanks again.

I'll test both methods for speed and simplicity.

pda

#8
Quote from: cameyo post_id=25005 time=1617113250 user_id=732
Function to create a function with name and parameters:
(define (make-add name val)
  (let (f nil)
    (setq f (string "(define (" name " x) (+ " val " x))"))
    (setq name (eval-string f))
  name))

Creating a function
(make-add "sum-10" 10)
out: (lambda (x) (+ 10 x))

Using the created function
(sum-10 3)
out: 13

Do you know of another way (instead of using strings) to create a function with another function?


your example of a made-add function to create a sum-10 function:



(define (make-add n v)
  (evaluate (list 'define (list n 'x) (list '+ v 'x))))


and using it:



(make-add 'sum-10 10)
out: (lambda (x) (+ 10 x))
(sum-10 3)
out: 13


a more general way to create any funcion with name n having parameters a and a body b with minor checking of parameters and function name:



(define (mkf n a b)
    (evaluate (and (symbol? n) (list 'define (if (apply and (map symbol? (cons n a))) (cons n a) n) b))))


and using it:



(mkf 'sum-x-y '(x y) '(+ x y))
out: (lambda (x y) (+ x y))
sum-x-y
out: (lambda (x y) (+ x y))
(sum-x-y 4 5)
out: 9


the function expects name and parameters to be symbols and defaults to a symbol definition if you pass bad parameters, that is paremeters which are not symbols, in this case is defines a symbol with the name passed and the evaluated body as value (or nil if evaluation fails). If the name of the function to be defined is not a symbols it returns nil and doesn't define anything:



x
out: nil
y
out: nil
(mkf 'sum-x-y-with-bad-parameters '(x y 3) '(+ x y))
out: ERR
sum-x-y-with-bad-parameters
out: nil
(define x 3)
out: 3
(define y 34)
out: 34
(mkf 'sum-x-y-with-bad-parameters '(x y 3) '(+ x y))
out: 37
sum-x-y-with-bad-parameters
out: 37
(mkf 4 '(x y 3) '(+ x y))
out: nil
(mkf nil '(x y) '(+ x y))
out: nil


Take this as an example about how to face the question, of course it needs more checking to be robust and correct (variable capture...).



Note: in this post "evaluate" means "eval", because phpBB does not allow me to type it even in code section, so assume this code as the very begining:


(define evaluate eval)

cameyo

#9
Thanks pda