Call an object method: Difference between revisions

Content added Content deleted
(→‎{{header|LFE}}: Updated to show how methods can call other methods)
(→‎{{header|LFE}}: Added more robust demonstration of objects and updating stored state.)
Line 296:
 
(defun fish-class (species)
"
(let (((binary (id (size 128))) (: crypto rand_bytes 16))
This is the constructor that will be used most often, only requiring that
(move-verb '"swam"))
one pass a 'species' string.
(lambda (message)
 
(case message
When the children are not defined, simply use an empty list.
"
(fish-class species ()))
 
(defun fish-class (species children)
"
This contructor is mostly useful as a way of abstracting out the id
generation from the larger constructor. Nothing else uses fish-class/2
besides fish-class/1, so it's not strictly necessary.
 
When the id isn't know, generate one."
(let* (((binary (id (size 128))) (: crypto rand_bytes 16))
(formatted-id (car
(: io_lib format
'"~32.16.0b" (list id)))))
(fish-class species children formatted-id)))
 
(defun fish-class (species children id)
"
This is the constructor used internally, once the children and fish id are
known.
"
(let ((move-verb '"swam"))
(lambda (method-name)
(case method-name
('id
(lambda (self) id))
(car
(: io_lib format
'"~32.16.0b" (list id)))))
('species
(lambda (self) species))
species))('children
(lambda (self) children))
('info
(lambda (self)
(: io format
'"id: ~p~nspecies: ~p~nchildren: ~p~n"
(list (get-id self) (get-species self)))))
(get-species self)
(get-children self)))))
('move
(lambda (self distance)
Line 320 ⟶ 345:
('reproduce
(lambda (self)
(let* ((child (fish-class species)))))))
(child-id (get-id child))
(children-ids (: lists append
(list children (list child-id))))
(parent-id (get-id self))
(parent (fish-class species children-ids parent-id)))
(list parent child))))
('children-count
(lambda (self)
(: erlang length children)))))))
 
(defun get-method (object method-name)
; define a function used for calling into the object (class instance)
"
(defun get-method (object command)
This is a generic function, used to call into the given object (class
(funcall object command))
instance).
"
(funcall object method-name))
 
; define object methods
Line 341 ⟶ 378:
(defun reproduce (object)
(funcall (get-method object 'reproduce) object))
 
(defun get-children (object)
(funcall (get-method object 'children) object))
 
(defun get-children-count (object)
(funcall (get-method object 'children-count) object))
</lang>
 
With this done, one can create objects and interact with them. Here is some usage from the LFE REPL:
<lang lisp>
; Load the file and create a fish-class instance:
> (slurp '"aquarium.lfe")
 
> (slurp '"object.lfe")
#(ok object)
> (set mommy-fish (fish-class '"Carp"))
#Fun<lfe_eval.10.91765564>
 
; Execute some of the basic methods:
 
> (get-species mommy-fish)
"Carp"
Line 354 ⟶ 402:
The Carp swam 17 feet!
ok
> (set baby-fish (reproduce mommy-fish))
#Fun<lfe_eval.10.91765564>
> (get-species baby-fish)
"Carp"
> (get-id mommy-fish)
"47eebe91a648f042fc3fb278df663de5"
"c549d68e63fedd0a631c5045ccd8fd7f"
 
> (get-info baby-fish)
; Now let's look at "modifying" state data (e.g., children counts):
id: "63f14d20e7c6fbffb6b692bfaf15f845"
 
> (get-children mommy-fish)
()
> (get-children-count mommy-fish)
0
> (set (mommy-fish baby-fish-1) (reproduce mommy-fish))
(#Fun<lfe_eval.10.91765564> #Fun<lfe_eval.10.91765564>)
> (get-id mommy-fish)
"47eebe91a648f042fc3fb278df663de5"
> (get-id baby-fish-1)
"fdcf35983bb496650e558a82e34c9935"
> (get-children-count mommy-fish)
1
> (set (mommy-fish baby-fish-2) (reproduce mommy-fish))
(#Fun<lfe_eval.10.91765564> #Fun<lfe_eval.10.91765564>)
> (get-id mommy-fish)
"47eebe91a648f042fc3fb278df663de5"
> (get-id baby-fish-2)
"3e64e5c20fb742dd88dac1032749c2fd"
> (get-children-count mommy-fish)
2
> (get-info mommy-fish)
id: "47eebe91a648f042fc3fb278df663de5"
species: "Carp"
children: ["fdcf35983bb496650e558a82e34c9935",
"3e64e5c20fb742dd88dac1032749c2fd"]
ok
</lang>