From: Tom Popovich Date: 2013-02-23T04:49:40+09:00 Subject: [ruby-core:52714] new feature : suggest - defclosure - similar to how labels in lisp can be used --047d7b2e3fc058091a04d6556404 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable class Xray # new feature : suggest (we should have a defclosure) a way to define a helper code that remembers # that the closure of variables reaches the upper block, below A and B would be defined as in # scope of 1 up. # # pretend that doXrayHelper_V1 was defined as: # # defclosure doXrayHelper_V1(c) ; a*3 + b*4 + c ; end # # and it stores a pointer the the enclosed scope, and only works within a function. # # =3D=3D=3D Motivation: # Q: 1 is there any way to do what lisp calls: labels # see @url: http://www.paulgraham.com/onlisptext.html for the following= : # # Using labels we can write a function analogous to list+, but in which the first argument to mapcar is a recursive function: # # (defun count-instances (obj lsts) # (labels ((instances-in (lst) # (if (consp lst) # (+ (if (eq (car lst) obj) 1 0) # (instances-in (cdr lst))) # 0))) # (mapcar #=92instances-in lsts))) # # above labels instances-in would be our defclosure instances-in , or defclosure doXrayHelper_V1(c) ... below. # # Q: 2 : what is the easiest way to efficiently define a helper method that really is very static but # is IN-A-FUNCTION and hidden scope to the method? # Attempts below: # 1. does not work because of local scope # 2. works, but no fnct hide; and is efficient # 3. works, via lambda define each function call, so not efficient ##################### V1 ######### # This will not work, you get: # `doXrayHelper_V1': undefined local variable or method `a' for # (NameError) # ruby_closure_speed.rb:14:in `doXray_V1' # ruby_closure_speed.rb:24:in `' ################################### def doXray_V1(a,b) def doXrayHelper_V1(c) a*3 + b*4 + c end doXrayHelper_V1(5) end ##################### V2 ######### # This will work, and is efficient but we have leaked the helper function outside the only place # that it is used ################################### def doXray_V2(a,b) doXrayHelper_V2(5,a,b) end def doXrayHelper_V2(c,a,b) ### function leaked here a*3 + b*4 + c end private :doXrayHelper_V2 ### make private so end users can not see, still it is seen in this class ##################### V3 ######### # This will work, but as you will see it is not very efficient in that we redefine the "helper fnct" that # we wanted to keep local to this function on each call. We get sample output of: # # ["... debug doXrayHelper_V3.object_id: ", 70229925414620] # ["... debug doXrayHelper_V3.object_id: ", 70229925414260] # ["... debug doXrayHelper_V3.object_id: ", 70229925413920] # ["... debug doXrayHelper_V3.object_id: ", 70229925413680] # ["... debug doXrayHelper_V3.object_id: ", 70229925413440] # ["... debug doXrayHelper_V3.object_id: ", 70229929690500] # # but look at all the work it does on each call, it creates another closure , when you compile lisp code # there it will be smarter that this is just a helper function. ################################### def doXray_V3(a,b) doXrayHelper_V3 =3D lambda do |c| a*3 + b*4 + c end p ["... debug doXrayHelper_V3.object_id: ", doXrayHelper_V3.object_id] doXrayHelper_V3.call(5) end end a =3D Xray.new a.doXray_V2(3,4) a.doXray_V3(3,4) a.doXray_V3(3,4) a.doXray_V3(3,4) a.doXray_V3(3,4) a.doXray_V3(3,4) a.doXray_V3(3,4) --047d7b2e3fc058091a04d6556404 Content-Type: text/html; charset=windows-1252 Content-Transfer-Encoding: quoted-printable class=A0 Xray


=A0 # new feature : suggest (we should have a defc= losure) a way to define a helper code that remembers
=A0 # that the clos= ure of variables reaches the upper block, below A and B would be defined as= in
=A0 # scope of 1 up.
=A0 #
=A0 # pretend that=A0 doXrayHelper_V1=A0 w= as defined as:
=A0 #
=A0 #=A0=A0=A0 defclosure doXrayHelper_V1(c) ;= =A0 a*3 + b*4 + c ; end
=A0 #
=A0 # and it stores a pointer the the e= nclosed scope, and only works within a function.
=A0 #
=A0 # =3D=3D=3D Motivation:
=A0 # Q: 1=A0 is there any way to d= o what lisp calls: labels
=A0 #=A0=A0 see @url: http://www.paulgraham.com/onlisptext.html= for the following:
=A0 #
=A0 # Using labels we can write a function analogous to list+, but= in which the first argument to mapcar is a recursive function:
=A0 #=A0 # (defun count-instances (obj lsts)
=A0 #=A0=A0 (labels ((instances= -in (lst)
=A0 #=A0=A0=A0=A0=A0 (if (consp lst)
=A0 #=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 (+ (if (eq (car lst) obj) 1 0)
=A0 #=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0 (instances-in (cdr lst)))
=A0 #=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0 0)))
=A0 #=A0=A0=A0 (mapcar #=92instances-in lsts)))
=A0 #
= =A0 #=A0 above=A0 labels instances-in=A0 would be our defclosure instances-= in , or=A0 defclosure doXrayHelper_V1(c) ... below.
=A0 #
=A0 # Q: 2 :=A0 what is the easiest way to efficiently define a he= lper method that really is very static but
=A0 #=A0=A0=A0=A0=A0=A0=A0=A0= is IN-A-FUNCTION=A0 and hidden scope to the method?

=A0 # Attempts = below:
=A0 # 1.=A0 does not work because of local scope
=A0 # 2.=A0 works, but no fnct hide; and is efficient
=A0 # 3.=A0 works,= via lambda define each function call, so not efficient

=A0 ########= #############=A0 V1 #########
=A0 # This will not work, you get:
=A0 = #=A0=A0=A0 `doXrayHelper_V1': undefined local variable or method `a'= ; for #<Xray:0x007ffd8d02e288> (NameError)
=A0=A0=A0 #=A0=A0=A0 ruby_closure_speed.rb:14:in `doXray_V1'
=A0 #= =A0=A0=A0 ruby_closure_speed.rb:24:in `<top (required)>'
=A0 #= ##################################
=A0 def doXray_V1(a,b)


=A0= =A0=A0 def doXrayHelper_V1(c)
=A0=A0=A0=A0=A0 a*3 + b*4 + c
=A0=A0=A0 end

=A0=A0=A0 doXrayHelpe= r_V1(5)

=A0 end


=A0 #####################=A0 V2 #########=
=A0 # This will work, and is efficient but we have leaked the helper fu= nction outside the only place
=A0 # that it is used
=A0 ###################################
=A0 def= doXray_V2(a,b)

=A0=A0=A0 doXrayHelper_V2(5,a,b)

=A0 end
<= br>=A0 def doXrayHelper_V2(c,a,b)=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ### func= tion leaked here
=A0=A0=A0 a*3 + b*4 + c
=A0 end
=A0 private=A0 :doXrayHelper_V2=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 ### make private so end users can not see, still it is seen in this cla= ss

=A0 #####################=A0 V3 #########
=A0 # This will=A0 w= ork, but as you will see it is not very efficient in that we redefine the &= quot;helper fnct" that
=A0 # we wanted to keep local to this function on each call.=A0 We get samp= le output of:
=A0 #
=A0 #=A0 ["... debug doXrayHelper_V3.object_= id: ", 70229925414620]
=A0 #=A0 ["... debug doXrayHelper_V3.ob= ject_id: ", 70229925414260]
=A0 #=A0 ["... debug doXrayHelper_V3.object_id: ", 70229925413920= ]
=A0 #=A0 ["... debug doXrayHelper_V3.object_id: ", 702299254= 13680]
=A0 #=A0 ["... debug doXrayHelper_V3.object_id: ", 7022= 9925413440]
=A0 #=A0 ["... debug doXrayHelper_V3.object_id: ", 70229929690500= ]
=A0 #
=A0 # but look at all the work it does on each call, it creat= es another closure , when you compile lisp code
=A0 # there it will be s= marter that this is just a helper function.
=A0 ###################################
=A0 def doXray_V3(a,b)

=A0=A0=A0 doXrayHelper_V3 =3D lambda do |c|
=A0=A0=A0=A0=A0 a*3 + b*4 = + c
=A0=A0=A0 end

=A0=A0=A0 p ["... debug doXrayHelper_V3.ob= ject_id: ", doXrayHelper_V3.object_id]

=A0=A0=A0 doXrayHelper_V3.call(5)

=A0 end

end


= a =3D Xray.new

a.doXray_V2(3,4)

a.doXray_V3(3,4)
a.doXray_= V3(3,4)
a.doXray_V3(3,4)
a.doXray_V3(3,4)
a.doXray_V3(3,4)
a.do= Xray_V3(3,4)
--047d7b2e3fc058091a04d6556404--