[EVALUATION] - E03 - jamLang Evaluation Case Applied to Ruby

R

Robert Klemme

Ilias Lazaridis said:
Robert Klemme wrote:
[...]
So, the last question for this part:

how can I add runtime-accessible [meta]data to a ruby function
definition?
[...]
I don't understand.

def talker

def sayHello
puts "Hello World"
end

def sayYourName
puts @name
end

end

how do I put a "hash" which keeps metadata to each _function_?

class Module
def meta() @meta ||= {} end
end

class Foo
def bar() end
meta[:bar] = "bar_meta"
end
[...]

the above is essentially "class metadata".

but it gives me the basic idea:

class Object
def meta() @meta ||= {} end
end

talker.sayYourName.meta[:author] = "it's just me"
puts talker.sayYourName.meta[:author]
=> it's just me

[i like this language *very* much]

-

But to understand this fully, can someone please decrypt this:

def meta()
@meta ||= {}
end

If @meta is something false (i.e. nil or false) then the expression on the
right hand side is evaluated and the result is assigned to @meta. It's
short for any of these

@meta = {} unless @meta
@meta || (@meta = {})
@meta or @meta = {}

{} creates a hash (synonym for Hash.new, but you can also put values there
like {"foo"=>"bar"}).

HTH

robert
 
I

Ilias Lazaridis

Robert Klemme wrote:
[...]
[i like this language *very* much]

-

But to understand this fully, can someone please decrypt this:

def meta()
@meta ||= {}
end

If @meta is something false (i.e. nil or false) then the expression on
the right hand side is evaluated and the result is assigned to @meta.
It's short for any of these

@meta = {} unless @meta
@meta || (@meta = {})
@meta or @meta = {}

{} creates a hash (synonym for Hash.new, but you can also put values
there like {"foo"=>"bar"}).

ok

you answer together with the other answer => i got it:

def meta() # use of "()" is optional
unless @meta # if @meta == nil ("unless" is the same as "if not")
@meta = {} # creates a new hash
end
@meta # returns the hash
end

..
 
C

Csaba Henk

[snip]

but it gives me the basic idea:

class Object
def meta() @meta ||= {} end
end

talker.sayYourName.meta[:author] = "it's just me"
puts talker.sayYourName.meta[:author]
=> it's just me

If you want metadata for the _function_, then it's not exactly the way
to go.

The sayYourName method, as defined above, is a side-effecting one,
writes out @name, then returns nil, which is a unique object, without
any reference to talker. That is, it's not a possible carrier of
metainformation.

What seems to be feasible is implementing one of the following
behaviours:

talker.meta[:sayYourName][:author] # => "it's just me"

or

talker.method:)sayYourName).meta[:author] # => "it's just me"

or if you are on steroids, maybe

talker.meta[:sayYourName].author

or

talker.method:)sayYourName).meta.author

(FYI, Object#method takes a symbol or a string, and returns the method
named thusly as an obejct.)

Csaba
 
I

Ilias Lazaridis

Anders said:
On Sun, Apr 03, 2005 at 08:39:42PM +0900, Ilias Lazaridis wrote:
[snipp]
But to understand this fully, can someone please decrypt this:

def meta()
@meta ||= {}
end

That's lazy initialization of the @meta variable. Another (and more
verbose) way to write it would be:

def meta()
unless @meta #If not defined, set the value
@meta = {}
end
@meta # Return Meta
end

def meta() # use of "()" is optional
unless @meta # if @meta == nil (unless = if not)
@meta = {} # creates a new hash
end
@meta # returns the (existing or new) hash
end
"@meta ||= {}" evaluates to "@meta = @meta || {}" and since the returned

"||=" similar to "+="

"||" means: if left operand is nil, pick right operand.
value from a method is the last evaluated expression "@meta ||= {}"
works.

ok, got it!

[will update the document soon - and hopefully can soon take the next round]

..
 
I

Ilias Lazaridis

Ilias said:
Ilias Lazaridis wrote: [...]
This document can serve as an flash-start (for people which simply
like to take a look on ruby).

http://lazaridis.com/case/lang/ruby.html

I hope you like the results so far.

I need to fill in the interactive session, to close this thread:

http://lazaridis.com/case/lang/index.html#run_interactive

http://lazaridis.com/case/lang/ruby.html#run_interactive

I've tried this:

open command window
change to project directory
cmd: irb
within irb
cmd: require 'talker'

talker is created, produces output.

but: the "talker" instance which was created during read in (of
talker.rb) has died.

why?

how do i read-in files, which produce instances, which 'survive'?

and: how do I delete an instance? [tried: del, delete, kill, rm, free]

..
 
S

Saynatkari

Le 3/4/2005 said:
Ilias said:
Ilias Lazaridis wrote: [...]
This document can serve as an flash-start (for people which simply
like to take a look on ruby).

http://lazaridis.com/case/lang/ruby.html

I hope you like the results so far.

I need to fill in the interactive session, to close this thread:

http://lazaridis.com/case/lang/index.html#run_interactive

http://lazaridis.com/case/lang/ruby.html#run_interactive

I've tried this:

open command window
change to project directory
cmd: irb
within irb
cmd: require 'talker'

talker is created, produces output.

but: the "talker" instance which was created during read in (of
talker.rb) has died.

why?

Local variables evaluated during a require() are not accessible
from outside the file; you may consider this such that the file
is the scope within which the variable is defined, just like in
a method body.
how do i read-in files, which produce instances, which 'survive'?

Global variables (although this practice would be discouraged),
which are identified by a $-prefix, e.g. $global = 'something'.
Come to think of it, constants may also be accessible.

Normally one will have either an accessor method of some sort
or simply provide the means of _creating_ an instance.
and: how do I delete an instance? [tried: del, delete, kill, rm, free]

One cannot explicitly delete an instance. It will be 'deleted'
(marked for garbage collection) once it is without references.

E

No-one expects the Solaris POSIX implementation!
 
I

Ilias Lazaridis

Saynatkari said:
Le 3/4/2005 said:
Ilias Lazaridis wrote:
[...]
I've tried this:

open command window
change to project directory
cmd: irb
within irb
cmd: require 'talker'

talker is created, produces output.

but: the "talker" instance which was created during read in (of
talker.rb) has died.

why?

Local variables evaluated during a require() are not accessible
from outside the file; you may consider this such that the file
is the scope within which the variable is defined, just like in
a method body.

I understand.

instead of 'require', can I use another command, like e.g. "expand".
how do i read-in files, which produce instances, which 'survive'?

Global variables (although this practice would be discouraged),
which are identified by a $-prefix, e.g. $global = 'something'.
Come to think of it, constants may also be accessible.
ok

Normally one will have either an accessor method of some sort
or simply provide the means of _creating_ an instance.
and: how do I delete an instance? [tried: del, delete, kill, rm, free]

One cannot explicitly delete an instance. It will be 'deleted'
(marked for garbage collection) once it is without references.

how can i reverse the process?

I like to kill the object, thus the destructor is called.

the references will point to nil.

..
 
I

Ilias Lazaridis

Csaba said:
def talker

def sayHello
puts "Hello World"
end

def sayYourName
puts @name
end

end
[snip]

but it gives me the basic idea:

class Object
def meta() @meta ||= {} end
end

talker.sayYourName.meta[:author] = "it's just me"
puts talker.sayYourName.meta[:author]
=> it's just me

If you want metadata for the _function_, then it's not exactly the way
to go.

The sayYourName method, as defined above, is a side-effecting one,
writes out @name, then returns nil, which is a unique object, without
any reference to talker. That is, it's not a possible carrier of
metainformation.

What seems to be feasible is implementing one of the following
behaviours:
[...] - (several other suggestions)

I like the extracted construct - and it works in practice.

Thus I'm covered in this point.

Thank you for your suggestions.

..
 
S

Saynatkari

Le 3/4/2005 said:
Csaba said:
def talker

def sayHello
puts "Hello World"
end

def sayYourName
puts @name
end

end
[snip]

but it gives me the basic idea:

class Object
def meta() @meta ||= {} end
end

talker.sayYourName.meta[:author] = "it's just me"
puts talker.sayYourName.meta[:author]
=> it's just me

If you want metadata for the _function_, then it's not exactly the way
to go.

The sayYourName method, as defined above, is a side-effecting one,
writes out @name, then returns nil, which is a unique object, without
any reference to talker. That is, it's not a possible carrier of
metainformation.

What seems to be feasible is implementing one of the following
behaviours:
[...] - (several other suggestions)

I like the extracted construct - and it works in practice.

Thus I'm covered in this point.

Thank you for your suggestions.

Just to make sure there is no confusion:

talker.sayYourName.meta[:author] = "it's just me"

sayYourName, when evaluated, returns nil. Therefore,
your meta structure is actually in the instance of
NilClass, not Talker. You should be able to test it
by trying nil.meta[:author] after you execute the
above code.

You would want to follow the original example,
or do something like this (you can elaborate
on the documentation notation):

class Object
def doc(str)
@doc_data ||= {}
# caller[1] will be the method name doc() was called from.
@doc_data[caller[1]] = str
end
end

class SomeClass
# Some method
def some_method
doc "This method does something."
# ...
end
end

E

No-one expects the Solaris POSIX implementation!
 
I

Ilias Lazaridis

Csaba said:
but it gives me the basic idea:

class Object
def meta() @meta ||= {} end
end

talker.sayYourName.meta[:author] = "it's just me"
puts talker.sayYourName.meta[:author]
=> it's just me

If you want metadata for the _function_, then it's not exactly the way
to go.

The sayYourName method, as defined above, is a side-effecting one,
writes out @name, then returns nil, which is a unique object, without
any reference to talker. That is, it's not a possible carrier of
metainformation.
[...]

after the other message and some more tests I understood you objections
and suggestion.

I sincerly apologize for rejecting them without further and deeper
evaluating them, trusting a little bit your experience.

I will continue tomorrow, as I've a blackout now.

..
 
I

Ilias Lazaridis

Saynatkari said:
[...]
but it gives me the basic idea:

class Object
def meta() @meta ||= {} end
end

talker.sayYourName.meta[:author] = "it's just me"
puts talker.sayYourName.meta[:author]
=> it's just me

If you want metadata for the _function_, then it's not exactly the way
to go.

The sayYourName method, as defined above, is a side-effecting one,
writes out @name, then returns nil, which is a unique object, without
any reference to talker. That is, it's not a possible carrier of
metainformation.
[...]
I like the extracted construct - and it works in practice.
[...]

Just to make sure there is no confusion:

talker.sayYourName.meta[:author] = "it's just me"

sayYourName, when evaluated, returns nil.

This behaviour seems non logical.

talker.sayYourName.meta

talker_object->sayYourName_object->meta_object
Class object Method object Hash object

The sayYourName Method Object is not executed, it's just a part of the
nested datastructure.
Therefore,
your meta structure is actually in the instance of
NilClass, not Talker. You should be able to test it
by trying nil.meta[:author] after you execute the
above code.

yes, i've verified this (with the quick test it seemed to work).

I've understood the example you give below.

But I like to have the metadata directly on my function.

And this without further indirection (at least not visual).
You would want to follow the original example,
or do something like this (you can elaborate
on the documentation notation):

class Object
def doc(str)
@doc_data ||= {}
# caller[1] will be the method name doc() was called from.
@doc_data[caller[1]] = str
end
end

class SomeClass
# Some method
def some_method
doc "This method does something."
# ...
end
end

..
 
S

Saynatkari

Le 3/4/2005 said:
Saynatkari said:
Le 3/4/2005 said:
Csaba Henk wrote:
On 2005-04-03, Ilias Lazaridis <[email protected]> wrote:
[...]
but it gives me the basic idea:

class Object
def meta() @meta ||= {} end
end

talker.sayYourName.meta[:author] = "it's just me"
puts talker.sayYourName.meta[:author]
=> it's just me

If you want metadata for the _function_, then it's not exactly the way
to go.

The sayYourName method, as defined above, is a side-effecting one,
writes out @name, then returns nil, which is a unique object, without
any reference to talker. That is, it's not a possible carrier of
metainformation.
[...]
I like the extracted construct - and it works in practice.
[...]

Just to make sure there is no confusion:

talker.sayYourName.meta[:author] = "it's just me"

sayYourName, when evaluated, returns nil.

This behaviour seems non logical.

talker.sayYourName.meta

talker_object->sayYourName_object->meta_object
Class object Method object Hash object

The sayYourName Method Object is not executed, it's just a part of the
nested datastructure.

You are not accessing the method, you are _calling_ the method.
As mentioned earlier, talker.method:)sayYourName).meta would
work.
Therefore,
your meta structure is actually in the instance of
NilClass, not Talker. You should be able to test it
by trying nil.meta[:author] after you execute the
above code.

yes, i've verified this (with the quick test it seemed to work).

I've understood the example you give below.

But I like to have the metadata directly on my function.

And this without further indirection (at least not visual).

This would require changes to the parser, so I do not see
it happening at least before 2.0. On the other hand, zenspider
promised on IRC to pay $50.00 to anyone who will patch the parser
to read comments into the AST, so...

In the interim, I think a fairly robust solution would be to
just write normal offline rdoc documentation for the source
code and then write some sort of a bridge that reads the
metadata in from the rdoc and either creates a .rb file that
can be included in one's program or directly extracts the
information from rdoc at runtime.
You would want to follow the original example,
or do something like this (you can elaborate
on the documentation notation):

class Object
def doc(str)
@doc_data ||= {}
# caller[1] will be the method name doc() was called from.
@doc_data[caller[1]] = str
end
end

class SomeClass
# Some method
def some_method
doc "This method does something."
# ...
end
end

..

E

No-one expects the Solaris POSIX implementation!
 
R

Robert Klemme

Saynatkari said:
Le 3/4/2005 said:
Saynatkari said:
Le 3/4/2005, "Ilias Lazaridis" <[email protected]> a écrit:
Csaba Henk wrote:

but it gives me the basic idea:

class Object
def meta() @meta ||= {} end
end

talker.sayYourName.meta[:author] = "it's just me"
puts talker.sayYourName.meta[:author]
=> it's just me

If you want metadata for the _function_, then it's not exactly the way
to go.

The sayYourName method, as defined above, is a side-effecting one,
writes out @name, then returns nil, which is a unique object, without
any reference to talker. That is, it's not a possible carrier of
metainformation. [...]

I like the extracted construct - and it works in practice. [...]

Just to make sure there is no confusion:

talker.sayYourName.meta[:author] = "it's just me"

sayYourName, when evaluated, returns nil.

This behaviour seems non logical.

talker.sayYourName.meta

talker_object->sayYourName_object->meta_object
Class object Method object Hash object

The sayYourName Method Object is not executed, it's just a part of the
nested datastructure.

You are not accessing the method, you are _calling_ the method.
As mentioned earlier, talker.method:)sayYourName).meta would
work.

No, it doesn't. Method instances are not suited to carrying meta data:
class Foo; def bar() end end => nil
Foo.new.method:)bar).meta[:test]="I'm here" => "I'm here"
f=Foo.new
=> # said:
f.method:)bar).meta[:test]="I'm here" => "I'm here"
f.method:)bar).meta[:test]
=> nil

The reason is that Method instances are created on each request:
=> 134636916

You have to stick to the class or object as point where meta data is stored.
If you want to store a hash per method you can do

class Object
def meta() @meta ||= Hash.new{|h,k| h[k]={}} end
end
f=Foo.new
=> # said:
f.meta[:bar][:info]="test" => "test"
f.meta[:bar] => {:info=>"test"}
f.meta[:bar][:info]
=> "test"

Kind regards

robert
 
C

Csaba Henk

Saynatkari said:
You are not accessing the method, you are _calling_ the method.
As mentioned earlier, talker.method:)sayYourName).meta would
work.

No, it doesn't. Method instances are not suited to carrying meta data:
[snip]

The reason is that Method instances are created on each request:

Hmm, that's interesting. Good to know of it. So then methods are not
objects per se, they just can be objectified.

Then really talker.meta[:sayYourName][:author] is the way to go. Of
course, if the metadata is not intended/needed to be instance-specific,
then it's better to be appended to the class.

Csaba
 
I

Ilias Lazaridis

Csaba said:
Saynatkari said:
You are not accessing the method, you are _calling_ the method.
As mentioned earlier, talker.method:)sayYourName).meta would
work.

No, it doesn't. Method instances are not suited to carrying meta data:
[snip]

The reason is that Method instances are created on each request:

Hmm, that's interesting. Good to know of it. So then methods are not
objects per se, they just can be objectified.

Then really talker.meta[:sayYourName][:author] is the way to go. Of
course, if the metadata is not intended/needed to be instance-specific,
then it's better to be appended to the class.

Csaba

Thank's to all replies.

I've understood now the problem.

-

The Ruby Object Model does not contain reflective MetaClasses, which
would enable to apply metadata even to methods.

-

I would like to know how a class which i've defined is represented in
memory, and how I can access it.

-

A Visual representation of the Relevant Ruby Object Model (e.g. with
UML) would be very helpfull to understand this immediately.

..
 
R

Robert Klemme

Ilias Lazaridis said:
Csaba said:
You are not accessing the method, you are _calling_ the method.
As mentioned earlier, talker.method:)sayYourName).meta would
work.

No, it doesn't. Method instances are not suited to carrying meta
data:

[snip]
The reason is that Method instances are created on each request:

Hmm, that's interesting. Good to know of it. So then methods are not
objects per se, they just can be objectified.

Then really talker.meta[:sayYourName][:author] is the way to go. Of
course, if the metadata is not intended/needed to be instance-specific,
then it's better to be appended to the class.

Csaba

Thank's to all replies.

I've understood now the problem.

-

The Ruby Object Model does not contain reflective MetaClasses, which
would enable to apply metadata even to methods.

I'm not sure what exactly you mean by this. You can indeed access classes
in Ruby. So I'd say there *are* MetaClasses. It's just that there is no
persistent representation of methods which you could augment with
additional data.
I would like to know how a class which i've defined is represented in
memory, and how I can access it.

You just access them like any object, only that class instances are
assigned to constants:
class Foo;end => nil
Foo.instance_variables => []
class Foo
class <<self
attr_accessor :bar
end
end => nil
Foo.bar = "test" => "test"
Foo.bar => "test"
Foo.instance_variables => ["@bar"]
o=Foo => Foo
o.new
=> # said:
A Visual representation of the Relevant Ruby Object Model (e.g. with
UML) would be very helpfull to understand this immediately.

I don't know whether such thing exists, but the concept is usually easy
grasped IMHO. Try to play a bit with classes in IRB - that helped me a
lot. Note especially methods #class, #ancestors and #superclass.

Kind regards

robert
 
C

Csaba Henk

A Visual representation of the Relevant Ruby Object Model (e.g. with
UML) would be very helpfull to understand this immediately.

You can find something like this at
http://www.ruby-doc.org/core/classes/Class.html -- though not UML just
simple ascii art.

You might as well enjoy "A Little Ruby, A Lot of Objects" by Brian
Marick (http://www.visibleworkings.com/little-ruby/). In the 3rd chapter
a visualization of the Ruby object model is worked out in a
step-by-step, deductive way (which is the methodology of the whole
work).

Csaba
 
J

James Edward Gray II

Then really talker.meta[:sayYourName][:author] is the way to go. Of
course, if the metadata is not intended/needed to be instance-specific,
then it's better to be appended to the class.

If the metadata has anything to do with method execution, say tracking
running time for example, you could implement accessors in Object and
call them in the method itself. From that call, caller() can be used
to index into some global hash that tracks the data.

Just thinking out loud here...

James Edward Gray II
 
J

James Edward Gray II

A Visual representation of the Relevant Ruby Object Model (e.g. with
UML) would be very helpfull to understand this immediately.

There are nice diagrams of this relationship in Programming Ruby
(Chapter 24: Objects and Classes).

James Edward Gray II
 
G

George Moschovitis

There are nice diagrams of this relationship in Programming Ruby
(Chapter 24: Objects and Classes).

or you can just use ri:

ri Class

generates an ASCII version of the diagrams.

George.
 

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,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top