RLisp - Lisp naturally embedded in Ruby

  • Thread starter Tomasz Wegrzanowski
  • Start date
T

Tomasz Wegrzanowski

1) I have really liked Ruby for the very reason that I can often
express algorithms from scheme/lisp directly in Ruby, but with a much
more readable syntax. Yes, This will be controversial to the lambda
devotees. However, my point is that Ruby can do this far easier than
languages like C or Java.

I agree that Ruby syntax is usually nicer.
However, it's a lot more difficult to play with macros if you have
Ruby-like syntax.
S-expressions make it much easier :)
 
C

Chad Perrin

2) The 'endless discussion' does seem to be a feature of learning to
program in Lisp. I suppose this may be because people who program in
Lisp give a lot of thought to details of both design and
implementation of software. However, I suspect that it may be that
Lisp attracts a certain amount of what we used to call 'rules lawyers'
at the gaming table.

While you may not want "rules lawyers" and "min-maxers" in your RPG
sessions, which are largely social events, there are some significant
advantages to be gained from such means of considering programming
problems. I'd rather have a "rules lawyer" writing my code than someone
who, conversely, doesn't think the rules matter.
 
T

Tomasz Wegrzanowski

No, that's just because a is global here. Shadow it by a local variable:

(defun foo ()
(let (a)
(setf a 3)
a))

a ; => 2
(foo) ; => 3
a ; => 2


That's why one uses LET for local variables. ;-)

Can we macro around it or something, so that
(set-local-variable variable value) introduces a function-local variable
without increasing indentation level each time it's being done?

I think it's reasonable to write something like that (whatever the names
of set-local-variable operator is):

(defun veclen (x y)
(set-local-variable x2 (* x x))
(set-local-variable y2 (* y y))
(set-local-variable z2 (+ x2 y2))
(sqrt z2)
)
 
O

Ola Bini

Tomasz said:
Can we macro around it or something, so that
(set-local-variable variable value) introduces a function-local variable
without increasing indentation level each time it's being done?

I think it's reasonable to write something like that (whatever the names
of set-local-variable operator is):

(defun veclen (x y)
(set-local-variable x2 (* x x))
(set-local-variable y2 (* y y))
(set-local-variable z2 (+ x2 y2))
(sqrt z2)
)

Such a macro would be a strange beast indeed. The problem is that
indentation level actually reflects lexical scope, which means that
set-local-variable would have to find the environment for the function
veclen and change this after it was defined. What you _could_ do if the
nesting is bad for you is to introduce CL's aux variables:
(defun veclen (x y &aux (x2 (* x x)) (y2 (* y y)) (z2 (+ x2 y2)))
(sqrt z2))

This is of course just syntactic sugar, but it works and is
standardized. I recommend you do this, keep setf/setq for changing the
variables, but leave let alone.

--
Ola Bini (http://ola-bini.blogspot.com)
JvYAML, RbYAML, JRuby and Jatha contributor
System Developer, Karolinska Institutet (http://www.ki.se)
OLogix Consulting (http://www.ologix.com)

"Yields falsehood when quined" yields falsehood when quined.
 
D

Daniel Martin

Tomasz Wegrzanowski said:
Can we macro around it or something, so that
(set-local-variable variable value) introduces a function-local variable
without increasing indentation level each time it's being done?

I think it's reasonable to write something like that (whatever the names
of set-local-variable operator is):

(defun veclen (x y)
(set-local-variable x2 (* x x))
(set-local-variable y2 (* y y))
(set-local-variable z2 (+ x2 y2))
(sqrt z2)
)

Well, you can't quite do that but you can easily do something like
this:

(defun veclen (x y)
(easy-local-progn
(local x2 (* x x))
(local y2 (* y y))
(local z2 (+ x2 y2))
(sqrt z2)
)
)

Or:

(defun-with-local veclen (x y)
(local x2 (* x x))
(local y2 (* y y))
(local z2 (+ x2 y2))
(sqrt z2)
)

(There may also be a way to override the standard meaning of "defun"
to have it do what your "defun-with-local" macro does, but I'd
recommend strongly against overriding standard parts of the language
like that)
 
T

Tomasz Wegrzanowski

Well, you can't quite do that but you can easily do something like
this:

(defun veclen (x y)
(easy-local-progn
(local x2 (* x x))
(local y2 (* y y))
(local z2 (+ x2 y2))
(sqrt z2)
)
)

Or:

(defun-with-local veclen (x y)
(local x2 (* x x))
(local y2 (* y y))
(local z2 (+ x2 y2))
(sqrt z2)
)

So, how would such a macro look like ?
 
O

Ola Bini

Tomasz said:
So, how would such a macro look like ?

You would have to do a code-walker (with all the glory such a thing
brings), find all places where you have local and more or less replace
them with let and let* each time you find one.

--
Ola Bini (http://ola-bini.blogspot.com)
JvYAML, RbYAML, JRuby and Jatha contributor
System Developer, Karolinska Institutet (http://www.ki.se)
OLogix Consulting (http://www.ologix.com)

"Yields falsehood when quined" yields falsehood when quined.
 
D

Daniel Martin

Tomasz Wegrzanowski said:
So, how would such a macro look like ?

Well, 1) This is ruby-talk, not comp.lang.lisp, and 2) I don't
actually know lisp.

But how hard can it be, right? .... (1.5 hours later) ....

Okay, try this:

(defun local-expander (bodylist)
(cond ((null bodylist) '())
((and (consp (car bodylist)) (eq (caar bodylist) 'local))
`((let ,(loop for x on (cdar bodylist)
by #'cddr
collect (list (car x) (cadr x)))
,@(local-expander (cdr bodylist)))))
(t (cons (car bodylist) (local-expander (cdr bodylist))))))

(defmacro progn-with-local (&rest body)
`(progn ,@(local-expander body)))

(defmacro defun-with-local (name args &rest body)
`(defun ,name ,args ,@(local-expander body)))

Then, you can do:

(defun-with-local pythag (x y)
(local x2 (* x x))
(local y2 (* y y))
(local z2 (+ x2 y2))
(sqrt z2))

Actually, you could even shorten that slightly to:

(defun-with-local pythag (x y)
(local x2 (* x x) y2 (* y y))
(local z2 (+ x2 y2))
(sqrt z2))

But I think that hurts the readability.

Note that you don't need to supply an initial value in the (local)
bit. Also, a (local) declaration will shadow references that follow
it, but not those that precede it. For example:

* (defvar a 'top)
A
* a
TOP
* (progn-with-local (setf a 'before) (local a) (setf a 'after))
AFTER
* a
BEFORE
 
T

Tomasz Wegrzanowski

Well, 1) This is ruby-talk, not comp.lang.lisp, and 2) I don't
actually know lisp.

But how hard can it be, right? .... (1.5 hours later) ....

Okay, try this:

(defun local-expander (bodylist)
(cond ((null bodylist) '())
((and (consp (car bodylist)) (eq (caar bodylist) 'local))
`((let ,(loop for x on (cdar bodylist)
by #'cddr
collect (list (car x) (cadr x)))
,@(local-expander (cdr bodylist)))))
(t (cons (car bodylist) (local-expander (cdr bodylist))))))

(defmacro progn-with-local (&rest body)
`(progn ,@(local-expander body)))

(defmacro defun-with-local (name args &rest body)
`(defun ,name ,args ,@(local-expander body)))

Then, you can do:

(defun-with-local pythag (x y)
(local x2 (* x x))
(local y2 (* y y))
(local z2 (+ x2 y2))
(sqrt z2))

Wow, I'm genuinely impressed by this macro.
Now I'll try to understand it ... :-D
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top